Merge remote-tracking branch 'goog/master' into nyc-dev

Bug: 27552463
Change-Id: If058b2de991c4813d49a5d844b8610405fb3bc5f
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..cc8b4da
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,14 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Known text files
+*.java text
+*.xml text
+*.yml text
+*.md text
+*.properties text
+*.sh text
+
+# Known binary files
+*.jar binary
+*.gif binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a73b2cd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+/build/
+target/
+bin/
+.project
+.classpath
+.settings/
+*~
+*.orig
+*.new
+.idea/
+*.iml
+*.ipr
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b9b79e0
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,37 @@
+language: java
+
+jdk:
+  - oraclejdk8
+  - oraclejdk7
+  - openjdk7
+  - openjdk6
+
+env:
+  global:
+    - secure: "WuvBM11o29dIluXelJpV1TFPqprFOlLEs6ES4LjvNKrtB/FT9g569Q63jnbg43ufs4fhQZKuqc3ue1KwZiWWozmkRTry8+2KimiCC0QRFc2UfWPy5BBlPepWahnkC5/CSnjQWtTVKzs67DobyCmAsU3mraOidQatXSpoOozGnNA="
+    - secure: "pAeI941ODNSo6F7A94WFafxYqp2kdeFTJksMLVHljT0h2nX6/236OXn/iZXiB+FbXe/DkQIHN3n1IZRwE8UJAbSAwoaPUWenPy4mNAhnI4L/rwysREwq5FKSFTWJet9HitfFR57ezLGOV0VLFfH1xGsNWabHzzbwbV3WMl9pH0M="
+    - secure: "Pqj194YmdK0va4bOkbjVG0wCZ7sbB5k3Qq66zSG2M26M21uHonwhXprdtSeYZ5Oy9fWcQte7jSA69euyYyLriDH6DU2NE34scK2Y1yO6SCfx5SGr3XuxHWqxtNOxoUaH4RP1WR/9CRkBg8kBxzWus3M2ZeqElu33/p2CtgJEdJg="
+  matrix:
+    - LABEL=ant        CMD="ant dist test.dist" INSTALL="/bin/true"
+    - LABEL=ant_no_aop CMD="ant -f build/no_aop/build.xml dist test.dist" INSTALL="ant no_aop"
+    - LABEL=mvn        CMD="mvn -P!standard-with-extra-repos verify --fail-at-end -Dsource.skip=true -Dmaven.javadoc.skip=true" INSTALL="mvn -P!standard-with-extra-repos dependency:go-offline test clean --quiet --fail-never -DskipTests=true"
+
+install:
+  - ${INSTALL}
+
+script:
+  - ${CMD}
+
+notifications:
+  email:
+    recipients:
+      - google-guice-dev+ci@googlegroups.com
+
+after_success:
+  - util/generate-latest-docs.sh
+  - util/compareBuilds.sh
+  - util/publish-snapshot-on-commit.sh
+
+branches:
+  only:
+    - master
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..87ef47f
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,123 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# 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.
+#
+
+#
+# Build support for guice within the Android Open Source Project
+# See https://source.android.com/source/building.html for more information
+#
+
+###################################
+#           Guice                 #
+###################################
+
+#
+# Builds the 'no_aop' flavor for Android.
+# -- see core/pom.xml NO_AOP rule.
+#
+guice_exclude_src_files := \
+  core/src/com/google/inject/spi/InterceptorBinding.java \
+  core/src/com/google/inject/internal/InterceptorBindingProcessor.java \
+  core/src/com/google/inject/internal/InterceptorStackCallback.java \
+  core/src/com/google/inject/internal/InterceptorStackCallback.java \
+  core/src/com/google/inject/internal/util/LineNumbers.java \
+  core/src/com/google/inject/internal/MethodAspect.java \
+  core/src/com/google/inject/internal/ProxyFactory.java
+
+guice_exclude_test_files := \
+  core/test/com/googlecode/guice/BytecodeGenTest.java \
+  core/test/com/google/inject/IntegrationTest.java \
+  core/test/com/google/inject/MethodInterceptionTest.java \
+  core/test/com/google/inject/internal/ProxyFactoryTest.java
+
+guice_munge_flags := \
+  -DNO_AOP
+#
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+
+guice_src_files_raw := $(call all-java-files-under,core/src)
+guice_test_files_raw := $(call all-java-files-under,core/test)
+guice_src_files := $(filter-out $(guice_exclude_src_files),$(guice_src_files_raw))
+guice_test_files := $(filter-out $(guice_exclude_test_files),$(guice_test_files_raw))
+munge_host_jar := $(HOST_OUT)/framework/munge-host.jar
+munge_zip_location := lib/build/munge.jar
+
+#
+# Host-side Java build
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := # None. Everything is post-processed by munge. See below.
+LOCAL_MODULE := guice-host
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := guavalib jsr330-host
+
+munge_src_arguments := $(guice_src_files)
+include $(LOCAL_PATH)/AndroidCallMunge.mk
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+
+#
+# Host-side Dalvik build
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := # None. Everything is post-processed by munge. See below.
+LOCAL_MODULE := guice-hostdex
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := guava-hostdex jsr330-hostdex
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+munge_src_arguments := $(guice_src_files)
+include $(LOCAL_PATH)/AndroidCallMunge.mk
+include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
+
+###################################
+#           Munge                 #
+###################################
+
+# This is required to post-process the guice source to strip out the AOP-specific code.
+# We build it from source (conveniently zipped inside of lib/build/munge.jar) instead
+# of relying on a prebuilt.
+
+munge_zipped_src_files_raw := $(filter %.java,$(shell unzip -Z1 "$(LOCAL_PATH)/$(munge_zip_location)"))
+munge_zipped_unsupported_files := MungeTask.java # Missing ant dependencies in Android.
+munge_zipped_src_files := $(filter-out $(munge_zipped_unsupported_files),$(munge_zipped_src_files_raw))
+
+#
+# We build munge from lib/build/munge.jar source code.
+#
+
+# (Munge) Host-side Java build
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := # None because we get everything by unzipping the munge jar first.
+LOCAL_MODULE := munge-host
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := junit
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+# Unzip munge and build it
+intermediates:= $(local-generated-sources-dir)
+GEN := $(addprefix $(intermediates)/, $(munge_zipped_src_files)) # List of all files that need to be patched.
+$(GEN) : PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN) : PRIVATE_INPUT_FILE := $(munge_zipped_src_files)
+$(GEN) : PRIVATE_ZIP_LOCATION := $(munge_zip_location)
+$(GEN) : PRIVATE_CUSTOM_TOOL = unzip -p "$(PRIVATE_PATH)/$(PRIVATE_ZIP_LOCATION)" $(shell echo $@ | awk -F / "{if (NF>1) {print \$$NF}}")  >$@ ## unzip -p munge.jar Filename.java > intermediates/Filename.java
+$(GEN): $(intermediates)/%.java : $(LOCAL_PATH)/$(PRIVATE_ZIP_LOCATION)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+
+# Rules for target, hostdex, etc., are omitted since munge is only used during the build.
+
+# TODO: Consider adding tests.
diff --git a/AndroidCallMunge.mk b/AndroidCallMunge.mk
new file mode 100644
index 0000000..404abf8
--- /dev/null
+++ b/AndroidCallMunge.mk
@@ -0,0 +1,42 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# 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.
+#
+
+#
+# Build support for guice within the Android Open Source Project
+# See https://source.android.com/source/building.html for more information
+#
+
+# Factored-out implementation of calling munge to post-process guice java files.
+#
+# Arguments:
+#  (Constant)
+#    munge_host_jar = Path to munge-host.jar (built by munge-host rule)
+#    munge_zip_location = Path to lib/build/munge.jar source archive
+#  (Varying)
+#    munge_src_arguments = List of files that need to be munged
+#    guice_munge_flags = List of flags to pass to munge (e.g. guice_munge_flags := -DNO_AOP)
+#
+
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+# Run munge over every single java file.
+intermediates:= $(local-generated-sources-dir)
+GEN := $(addprefix $(intermediates)/, $(munge_src_arguments)) # List of all files that need to be munged.
+$(GEN) : PRIVATE_ZIP_LOCATION := $(munge_zip_location)
+$(GEN) : PRIVATE_HOST_JAR := $(munge_host_jar)
+$(GEN) : PRIVATE_MUNGE_FLAGS := $(guice_munge_flags)
+$(GEN) : PRIVATE_CUSTOM_TOOL = java -cp $(PRIVATE_HOST_JAR) Munge $(PRIVATE_MUNGE_FLAGS) $< > $@
+$(GEN): $(intermediates)/%.java : $(LOCAL_PATH)/%.java $(LOCAL_PATH)/$(munge_zip_location) $(munge_host_jar)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..1405580
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,61 @@
+# How to contribute #
+
+We'd love to accept your patches and contributions to this project.  There are
+a just a few small guidelines you need to follow.
+
+
+## Contributor License Agreement ##
+
+Contributions to any Google project must be accompanied by a Contributor
+License Agreement.  This is not a copyright **assignment**, it simply gives
+Google permission to use and redistribute your contributions as part of the
+project.
+
+  * If you are an individual writing original source code and you're sure you
+    own the intellectual property, then you'll need to sign an [individual
+    CLA][].
+
+  * If you work for a company that wants to allow you to contribute your work,
+    then you'll need to sign a [corporate CLA][].
+
+You generally only need to submit a CLA once, so if you've already submitted
+one (even if it was for a different project), you probably don't need to do it
+again.
+
+[individual CLA]: https://developers.google.com/open-source/cla/individual
+[corporate CLA]: https://developers.google.com/open-source/cla/corporate
+
+
+## Submitting a patch ##
+
+  1. It's generally best to start by opening a new issue describing the bug or
+     feature you're intending to fix.  Even if you think it's relatively minor,
+     it's helpful to know what people are working on.  Mention in the initial
+     issue that you are planning to work on that bug or feature so that it can
+     be assigned to you.
+
+  1. Follow the normal process of [forking][] the project, and setup a new
+     branch to work in.  It's important that each group of changes be done in
+     separate branches in order to ensure that a pull request only includes the
+     commits related to that bug or feature.
+
+  1. Any significant changes should almost always be accompanied by tests.  The
+     project already has good test coverage, so look at some of the existing
+     tests if you're unsure how to go about it.
+     
+  1. All contributions must be licensed Apache 2.0 and all files must have
+     a copy of the boilerplate licence comment (can be copied from an existing
+     file.  Files should be formatted according to Google's [java style guide][].
+
+  1. Do your best to have [well-formed commit messages][] for each change.
+     This provides consistency throughout the project, and ensures that commit
+     messages are able to be formatted properly by various git tools.
+
+  1. Finally, push the commits to your fork and submit a [pull request][].
+
+[forking]: https://help.github.com/articles/fork-a-repo
+[java style guide]: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html
+[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
+[pull request]: https://help.github.com/articles/creating-a-pull-request
+
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..56b1b86
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,57 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+
+# Clean up generated code from guice-hostdex
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/gen/JAVA_LIBRARIES/guice-hostdex_intermediates)/path/to/file.java
+# Clean up generated code from guice-host
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/gen/JAVA_LIBRARIES/guice-host_intermediates)/path/to/file.java
+
+# Clean up generated code from munge-host
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/gen/JAVA_LIBRARIES/munge-host_intermediates)/path/to/file.java
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a86d992
--- /dev/null
+++ b/README.md
@@ -0,0 +1,24 @@
+Guice
+====
+
+**Latest version: [4.0](https://github.com/google/guice/wiki/Guice40)!**
+
+**Documentation:** [User Guide](https://github.com/google/guice/wiki/Motivation), [4.0 javadocs](http://google.github.io/guice/api-docs/4.0/javadoc/packages.html), [Latest javadocs](http://google.github.io/guice/api-docs/latest/javadoc/index.html) <br/>
+**Continuous Integration:** [![Build Status](https://api.travis-ci.org/google/guice.png?branch=master)](https://travis-ci.org/google/guice) <br
+/>
+**Mailing Lists:** [User Mailing List](http://groups.google.com/group/google-guice), [Developer Mailing List](http://groups.google.com/group/google-guice-dev) <br/>
+**License:** [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0)
+
+Put simply, Guice alleviates the need for factories and the use of new in your Java code. Think of Guice's @Inject as the new new. You will still need to write factories in some cases, but your code will not depend directly on them. Your code will be easier to change, unit test and reuse in other contexts.
+
+Guice embraces Java's type safe nature, especially when it comes to features introduced in Java 5 such as generics and annotations. You might think of Guice as filling in missing features for core Java. Ideally, the language itself would provide most of the same features, but until such a language comes along, we have Guice.
+
+Guice helps you design better APIs, and the Guice API itself sets a good example. Guice is not a kitchen sink. We justify each feature with at least three use cases. When in doubt, we leave it out. We build general functionality which enables you to extend Guice rather than adding every feature to the core framework.
+
+Guice aims to make development and debugging easier and faster, not harder and slower. In that vein, Guice steers clear of surprises and magic. You should be able to understand code with or without tools, though tools can make things even easier. When errors do occur, Guice goes the extra mile to generate helpful messages.
+
+For an introduction to Guice and a comparison to new and the factory pattern, see [Bob Lee's video presentation](https://www.youtube.com/watch?v=hBVJbzAagfs). After that, check out our [user's guide](https://github.com/google/guice/wiki/Motivation).
+
+We've been running Guice in mission critical applications since 2006, and now you can, too. We hope you enjoy it as much as we do.
+
+[![jolt award](http://crazybob.org/jolt.png)](http://joltawards.com)
diff --git a/README.version b/README.version
new file mode 100644
index 0000000..d3de1cd
--- /dev/null
+++ b/README.version
@@ -0,0 +1,4 @@
+URL: https://github.com/google/guice
+Version: 4.0 (5a209e98e0dedf3dbb2cc657514e7daf1707296c)
+BugComponent: 99142
+Owners: iam
diff --git a/bom/pom.xml b/bom/pom.xml
new file mode 100644
index 0000000..81d2315
--- /dev/null
+++ b/bom/pom.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject</groupId>
+    <artifactId>guice-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <packaging>pom</packaging>
+
+  <artifactId>guice-bom</artifactId>
+
+  <name>Google Guice - Bill of Materials</name>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>com.google.inject</groupId>
+        <artifactId>guice</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject</groupId>
+        <artifactId>guice</artifactId>
+        <version>${project.version}</version>
+        <classifier>no_aop</classifier>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject</groupId>
+        <artifactId>guice</artifactId>
+        <version>${project.version}</version>
+        <classifier>classes</classifier>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-assistedinject</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-dagger-adapter</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-grapher</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-jmx</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-jndi</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-multibindings</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-persist</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-servlet</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-spring</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-struts2</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-testlib</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-throwingproviders</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+<!--
+ |  not yet promoted...
+- -
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-mini</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject.extensions</groupId>
+        <artifactId>guice-service</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+-->
+    </dependencies>
+  </dependencyManagement>
+</project>
diff --git a/build.properties b/build.properties
new file mode 100644
index 0000000..cca000c
--- /dev/null
+++ b/build.properties
@@ -0,0 +1,40 @@
+lib.dir=lib
+src.dir=core/src
+test.dir=core/test
+servlet.src.dir=extensions/servlet/src
+spring.src.dir=extensions/spring/src
+assistedinject.src.dir=extensions/assistedinject/src
+jmx.src.dir=extensions/jmx/src
+jndi.src.dir=extensions/jndi/src
+throwingproviders.src.dir=extensions/throwingproviders/src
+multibindings.src.dir=extensions/multibindings/src
+daggeradapter.src.dir=extensions/dagger-adapter/src
+privatemodules.src.dir=extensions/privatemodules/src
+lifecycle.src.dir=extensions/lifecycle/src
+persist.src.dir=extensions/persist/src
+struts2.src.dir=extensions/struts2/src
+grapher.src.dir=extensions/grapher/src
+testlib.src.dir=extensions/testlib/src
+build.dir=build
+javadoc.packagenames=com.google.inject,com.google.inject.spi,\
+  com.google.inject.matcher,\
+  com.google.inject.servlet,\
+  com.google.inject.name,\
+  com.google.inject.tools.jmx,\
+  com.google.inject.binder,\
+  com.google.inject.jndi,\
+  com.google.inject.spring,\
+  com.google.inject.assistedinject,\
+  com.google.inject.throwingproviders,\
+  com.google.inject.multibindings,\
+  com.google.inject.daggeradapter,\
+  com.google.inject.privatemodules,\
+  com.google.inject.util,\
+  com.google.inject.persist,\
+  com.google.inject.persist.finder,\
+  com.google.inject.persist.jpa,\
+  com.google.inject.testing,\
+  com.google.inject.testing.fieldbinder
+test.class=com.google.inject.AllTests
+module=com.google.inject
+imports=!net.sf.cglib.*,!org.objectweb.asm.*
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..3d0c772
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+
+<project name="guice" default="compile">
+  <!-- common definitions are stored in common.xml. -->
+  <import file="common.xml"/>
+
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+  </path>
+  
+  <path id="javadoc.classpath">
+    <path refid="compile.classpath"/>
+    <fileset dir="extensions">
+      <include name="*/lib/*.jar"/>
+    </fileset>
+    <pathelement location="${build.dir}/classes"/>
+  </path>
+
+
+  <target name="jar" depends="jar.withdeps, manifest" description="Build jar.">
+    <jar jarfile="${build.dir}/dist/guice-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <zipfileset src="${build.dir}/${ant.project.name}-with-deps.jar"/>
+    </jar>
+  </target>
+
+  <target name="dist" depends="distjars, javadoc"
+       description="Build entire distribution.">
+    <ant antfile="extensions/servlet/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/spring/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/struts2/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/assistedinject/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/jmx/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/jndi/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/throwingproviders/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/multibindings/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/dagger-adapter/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/persist/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/grapher/build.xml" target="distjars" inheritAll="false"/>
+    <ant antfile="extensions/testlib/build.xml" target="distjars" inheritAll="false"/>
+
+    <copy toDir="${build.dir}/dist"> 
+      <fileset dir="extensions/servlet/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist"> 
+      <fileset dir="extensions/spring/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/struts2/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/assistedinject/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/jmx/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/jndi/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/throwingproviders/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/multibindings/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/dagger-adapter/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/persist/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/grapher/build" includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist">
+      <fileset dir="extensions/testlib/build" includes="*.jar"/>
+    </copy>
+
+    <copy toDir="${build.dir}/dist" file="COPYING"/> 
+    <copy toDir="${build.dir}/dist"> 
+      <fileset dir="${lib.dir}" 
+        includes="*.jar"/>
+    </copy>
+    <copy toDir="${build.dir}/dist"> 
+      <fileset dir="${build.dir}" includes="javadoc/**/*"/>
+    </copy>
+
+    <zip destfile="${build.dir}/guice-${version}.zip">
+      <zipfileset dir="${build.dir}/dist" prefix="guice-${version}" excludes="*-src.jar"/>
+    </zip>
+    <zip destfile="${build.dir}/guice-${version}-src.zip">
+      <zipfileset dir="." prefix="guice-${version}-src"
+          excludes="build/**,**/.svn/**,classes/**,.settings/**,bin/**,latest-api-diffs/**,latest-javadoc/**,.classpath,.project"/>
+    </zip>
+  </target>
+
+  <target name="test.dist"
+    description="Execute JUnit tests against distribution jar.">
+    <antcall target="test.dist.run">
+      <param name="jvmarg-value" value="-Dguice_include_stack_traces="/>
+    </antcall>
+    <antcall target="test.dist.run">
+      <param name="jvmarg-value" value="-Dguice_include_stack_traces=OFF"/>
+    </antcall>
+    <antcall target="test.dist.run">
+      <param name="jvmarg-value" value="-Dguice_include_stack_traces=COMPLETE"/>
+    </antcall>
+  </target>
+
+  <target name="test.dist.run"
+    depends="jar, test.withdeps"
+    description="Execute JUnit tests against distribution jar with the given jvmarg.">
+    <java fork="true"
+        classname="junit.textui.TestRunner"
+        failonerror="true"
+        taskname="junit">
+      <classpath>
+        <pathelement location="${build.dir}/guice-${version}-tests.jar"/>
+        <pathelement location="${build.dir}/dist/guice-${version}.jar"/>
+        <pathelement location="lib/javax.inject.jar"/>
+        <pathelement location="lib/aopalliance.jar"/>
+        <pathelement location="lib/guava-16.0.1.jar"/>
+        <pathelement location="lib/build/guava-testlib-16.0.1.jar"/>
+        <pathelement location="lib/build/junit.jar"/>
+        <pathelement location="lib/build/servlet-api-2.5.jar"/>
+        <pathelement location="lib/build/easymock.jar"/>
+        <pathelement location="lib/build/javax.inject-tck.jar"/>
+        <pathelement location="lib/build/bnd-0.0.384.jar"/>
+        <pathelement location="lib/build/felix-2.0.5.jar"/>
+      </classpath>
+      <arg value="com.google.inject.AllTests"/>
+      <jvmarg value="${jvmarg-value}"/>
+      <syspropertyset>
+        <propertyref name="version"/>
+        <propertyref name="build.dir"/>
+        <propertyref name="lib.dir"/>
+      </syspropertyset>
+    </java>
+  </target>
+
+  <property name="old.api" value="3.0"/>
+  <property name="new.api" value="latest"/>
+  <target name="jdiff" depends="compile">
+    <property name="jdiff.home" value="lib/build/jdiff"/>
+    <property name="jdiff.tmp" value="build/docs/latest-api-diffs"/>
+    <delete dir="${jdiff.tmp}"/>
+    <mkdir dir="${jdiff.tmp}"/>
+
+    <!-- Generate API for current version. -->
+    <javadoc packagenames="com.google.*"
+             docletpath="${jdiff.home}/jdiff.jar${path.separator}${jdiff.home}/xerces.jar"
+             maxmemory="1024M"
+             classpathref="javadoc.classpath">
+      <fileset dir="${src.dir}" defaultexcludes="yes">
+        <include name="com/google/**"/>
+        <exclude name="com/google/inject/internal/**"/>
+      </fileset>
+      <fileset dir="${servlet.src.dir}"/>
+      <fileset dir="${spring.src.dir}"/>
+      <fileset dir="${assistedinject.src.dir}"/>
+      <fileset dir="${jmx.src.dir}"/>
+      <fileset dir="${jndi.src.dir}"/>
+      <fileset dir="${throwingproviders.src.dir}"/>
+      <fileset dir="${multibindings.src.dir}"/>
+      <fileset dir="${daggeradapter.src.dir}"/>
+      <fileset dir="${persist.src.dir}"/>
+      <fileset dir="${struts2.src.dir}"/>
+      <fileset dir="${grapher.src.dir}"/>
+      <fileset dir="${testlib.src.dir}"/>
+
+      <doclet name="jdiff.JDiff" path="${jdiff.home}/jdiff.jar:${jdiff.home}/xerces.jar">
+        <param name="-apidir" value="${jdiff.tmp}" />
+        <param name="-apiname" value="${new.api}" />
+      </doclet>
+    </javadoc>
+
+    <!-- Do a diff against the previous version. -->
+    <javadoc packagenames="com.google.*"
+             destdir="${jdiff.tmp}"
+             docletpath="${jdiff.home}/jdiff.jar${path.separator}${jdiff.home}/xerces.jar"
+             maxmemory="512M"
+             sourcefiles="${jdiff.home}/Null.java"
+             classpathref="javadoc.classpath">
+      <doclet name="jdiff.JDiff">
+        <param name="-oldapi" value="${old.api}"/>
+        <param name="-oldapidir" value="latest-api-diffs"/>
+        <param name="-javadocold" value="http://google.github.io/guice/api-docs/${old.api}/javadoc/"/>
+        <param name="-newapi" value="${new.api}"/>
+        <param name="-newapidir" value="${jdiff.tmp}"/>
+        <param name="-javadocnew" value="http://google.github.io/guice/api-docs/${new.api}/javadoc/"/>
+        <param name="-stats"/>
+        <param name="-docchanges"/>
+      </doclet>
+    </javadoc>
+  </target>
+
+  <target name="javadoc" depends="compile">
+    <javadoc packagenames="com.google.*"
+             destdir="build/docs/javadoc"
+             maxmemory="512M"
+             classpathref="javadoc.classpath"
+             additionalparam="-Xdoclint:none -notimestamp"
+             windowtitle="Guice ${new.api} API"
+             author="false"
+             protected="true">
+      <group title="Guice Core" packages="com.google.inject:com.google.inject.util:com.google.inject.spi:com.google.inject.name:com.google.inject.matcher:com.google.inject.binder"/>
+      <fileset dir="${src.dir}" defaultexcludes="yes">
+        <include name="com/google/inject/**"/>
+        <exclude name="com/google/inject/internal/**"/>
+      </fileset>      
+
+      <group title="Servlet Extension" packages="com.google.inject.servlet"/>
+      <fileset dir="${servlet.src.dir}"/>
+
+      <group title="AssistedInject Extension" packages="com.google.inject.assistedinject"/>
+      <fileset dir="${assistedinject.src.dir}"/>
+      
+      <group title="Multibinder Extension" packages="com.google.inject.multibindings"/>
+      <fileset dir="${multibindings.src.dir}"/>
+
+      <group title="Dagger Adapter" packages="com.google.inject.daggeradapter"/>
+      <fileset dir="${daggeradapter.src.dir}"/>
+
+      <group title="ThrowingProviders Extension" packages="com.google.inject.throwingproviders"/>
+      <fileset dir="${throwingproviders.src.dir}"/>
+
+      <group title="Test Libraries Extension" packages="com.google.inject.testing.*"/>
+      <fileset dir="${testlib.src.dir}"/>
+
+      <group title="Grapher Extension" packages="com.google.inject.grapher:com.google.inject.grapher.*"/>
+      <fileset dir="${grapher.src.dir}"/>
+
+      <group title="Persist Extension" packages="com.google.inject.persist:com.google.inject.persist.*"/>
+      <fileset dir="${persist.src.dir}"/>
+
+      <group title="Spring Extension" packages="com.google.inject.spring"/>
+      <fileset dir="${spring.src.dir}"/>
+
+      <group title="Struts2 Extension" packages="com.google.inject.struts2"/>
+      <fileset dir="${struts2.src.dir}"/> 
+
+      <group title="JNDI Extension" packages="com.google.inject.jndi"/>     
+      <fileset dir="${jndi.src.dir}"/>
+
+      <group title="JMX Extension" packages="com.google.inject.tools.jmx"/>
+      <fileset dir="${jmx.src.dir}"/>      
+
+      <link href="http://aopalliance.sourceforge.net/doc/"/>
+      <link href="http://docs.oracle.com/javase/7/docs/api/"/>
+      <link href="http://atinject.googlecode.com/svn/trunk/javadoc/"/>
+      <link href="http://docs.guava-libraries.googlecode.com/git/javadoc/"/>
+      <link href="https://tomcat.apache.org/tomcat-5.5-doc/servletapi/"/>
+    </javadoc>
+  </target>
+
+  <target name="no_aop"
+          description="Create a copy of the Guice source that doesn't do bytecode generation.">
+    <taskdef name="munge" classname="MungeTask" classpath="lib/build/munge.jar"/>
+    <mkdir dir="build/no_aop"/>
+    <munge todir="build/no_aop">
+      <fileset dir=".">
+        <!-- exclude generated files -->
+        <exclude name="build/**"/>
+        <exclude name="classes/**"/>
+        <exclude name="latest-api-diffs/**"/>
+        <exclude name="javadoc/**"/>
+        <exclude name="latest-javadoc/**"/>
+        <!-- exclude AOP-specific libraries -->
+        <exclude name="lib/aopalliance.jar"/>
+        <exclude name="lib/build/asm-*.jar"/>
+        <exclude name="lib/build/cglib-*.jar"/>
+        <!-- exclude AOP-specific classes -->
+        <exclude name="**/LineNumbers.java"/>
+        <exclude name="**/InterceptorBindingProcessor.java"/>
+        <exclude name="**/ProxyFactory.java"/>
+        <exclude name="**/ProxyFactoryTest.java"/>
+        <exclude name="**/InterceptorStackCallback.java"/>
+        <exclude name="**/InterceptorBinding.java"/>
+        <exclude name="**/MethodAspect.java"/>
+        <exclude name="**/MethodInterceptionTest.java"/>
+        <exclude name="**/BytecodeGenTest.java"/>
+        <exclude name="**/IntegrationTest.java"/>
+        <exclude name="**/MethodInterceptionTest.java"/>
+      </fileset>
+      <arg value="-DNO_AOP" />
+    </munge>
+    <replace file="build/no_aop/common.xml" value="">
+      <replacetoken><![CDATA[<zipfileset src="${common.basedir}/lib/build/asm-5.0.3.jar"/>]]></replacetoken>
+    </replace>
+    <replace file="build/no_aop/common.xml" value="">
+      <replacetoken><![CDATA[<zipfileset src="${common.basedir}/lib/build/cglib-3.1.jar"/>]]></replacetoken>
+    </replace>
+    <replace file="build/no_aop/common.xml" value="">
+      <replacetoken><![CDATA[<zipfileset src="${common.basedir}/lib/build/cglib-3.1.jar"><include name="LICENSE"/><include name="NOTICE"/></zipfileset>]]></replacetoken>
+    </replace>
+    <replace file="build/no_aop/common.xml" value='Bundle-Name" value="$${ant.project.name} (no_aop)'>
+      <replacetoken><![CDATA[Bundle-Name" value="${ant.project.name}]]></replacetoken>
+    </replace>
+  </target>
+
+  <target name="clean.all"
+      depends="clean"
+      description="Remove generated files.">
+    <ant dir="extensions/servlet" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/spring" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/struts2" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/assistedinject" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/jmx" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/jndi" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/throwingproviders" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/multibindings" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/dagger-adapter" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/persist" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/grapher" antfile="build.xml" target="clean"/>
+    <ant dir="extensions/testlib" antfile="build.xml" target="clean"/>
+  </target>
+
+</project>
diff --git a/common.xml b/common.xml
new file mode 100644
index 0000000..a23eb90
--- /dev/null
+++ b/common.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0"?>
+
+<project name="common">
+
+  <property file="build.properties"/>
+
+  <!-- can be overridden at the command line with -Dversion=
+       or in IDEA, in the ant properties dialog -->
+  <property name="version" value="snapshot"/>
+  <property name="api.version" value="1.4"/>
+
+  <target name="compile" description="Compile Java source.">
+    <mkdir dir="${build.dir}/classes"/>
+    <javac srcdir="${src.dir}"
+         debug="on"
+         destdir="${build.dir}/classes"
+         source="1.6" target="1.6" includeantruntime="false">
+      <compilerarg value="-Xlint:all,-serial"/>
+      <classpath refid="compile.classpath"/>
+    </javac>
+    <copy toDir="${build.dir}/classes">
+      <fileset dir="${src.dir}" excludes="**/*.java"/>
+    </copy>
+  </target>
+
+  <target name="manifest" description="Generate OSGi manifest." depends="compile">
+    <dirname property="common.basedir" file="${ant.file.common}"/>
+    <taskdef resource="aQute/bnd/ant/taskdef.properties"
+      classpath="${common.basedir}/lib/build/bnd-0.0.384.jar"/>
+
+    <fail unless="module" message="Missing 'module' property (use the primary package name in this jar)"/>
+    <property name="imports" value=""/>
+
+    <property name="Bundle-Name" value="${ant.project.name}"/>
+    <property name="Bundle-SymbolicName" value="${module}"/>
+    <property name="Bundle-Version" value="${replace;${version};^[^0-9];0.0.0.$0}"/>
+
+    <property name="Bundle-Description" value="Guice is a lightweight dependency injection framework for Java 6 and above"/>
+    <property name="Bundle-DocURL" value="https://github.com/google/guice"/>
+    <property name="Bundle-Copyright" value="Copyright (C) 2006 Google Inc."/>
+    <property name="Bundle-License" value="http://www.apache.org/licenses/LICENSE-2.0.txt"/>
+    <property name="Bundle-RequiredExecutionEnvironment" value="JavaSE-1.6"/>
+    <property name="Bundle-Vendor" value="Google, Inc."/>
+
+    <property name="Export-Package" value="!${module}.internal.*,${module}.*;version=${api.version}"/>
+
+    <condition property="Eclipse-ExtensibleAPI" value="true">
+      <equals arg1="${module}" arg2="com.google.inject"/>
+    </condition>
+
+    <condition property="Import-Package" value="!com.google.inject.*,*" else="!${module}.*,${imports},*">
+      <istrue value="${fragment}"/>
+    </condition>
+
+    <condition property="Fragment-Host" value="com.google.inject">
+      <istrue value="${fragment}"/>
+    </condition>
+
+    <property name="-nouses" value="true"/>
+
+    <property name="-removeheaders" value="Bnd-LastModified,Ignore-Package,Include-Resource,Private-Package,Tool"/>
+
+    <bndwrap jars="${build.dir}/classes" output="${build.dir}"/>
+
+    <unjar src="${build.dir}/classes.bar" dest="${build.dir}">
+      <patternset>
+        <include name="META-INF/MANIFEST.MF"/>
+      </patternset>
+    </unjar>
+  </target>
+
+  <target name="test.compile"
+      depends="compile"
+      description="Compile test source.">
+    <mkdir dir="${build.dir}/test"/>
+    <javac srcdir="${test.dir}"
+         debug="on"
+         destdir="${build.dir}/test"
+         source="1.6" target="1.6" includeantruntime="false">
+      <classpath path="${build.dir}/classes"/>
+      <classpath path="${build.dir}/test"/>
+      <classpath refid="compile.classpath"/>
+    </javac>
+    <copy toDir="${build.dir}/test">
+      <fileset dir="${test.dir}" excludes="**/*.java"/>
+    </copy>
+  </target>
+
+  <target name="test"
+      depends="test.compile"
+      description="Execute JUnit tests.">
+    <java fork="true"
+        classname="junit.textui.TestRunner"
+        failonerror="true"
+        taskname="junit">
+      <classpath>
+        <pathelement location="${build.dir}/test"/>
+        <pathelement location="${build.dir}/classes"/>
+        <path refid="compile.classpath"/>
+      </classpath>
+      <arg value="${test.class}"/>
+    </java>
+  </target>
+
+  <target name="clean"
+      description="Remove generated files.">
+    <delete dir="${build.dir}"/>
+  </target>
+
+  <target name="source.jar"
+      description="Create a .jar file with sources">
+    <mkdir dir="${build.dir}"/>
+    <zip destfile="${build.dir}/${ant.project.name}-${version}-src.jar">
+      <fileset dir="${src.dir}"/>
+    </zip>
+  </target>
+
+  <target name="distjars"
+      depends="source.jar, jar"
+      description="Build jar files"/>
+
+  <target name="test.withdeps" depends="test.compile"
+      description="Build a jar of tests with internal.util refocused.">
+    <mkdir dir="${build.dir}/dist"/>
+    <dirname property="common.basedir" file="${ant.file.common}"/>
+    <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask"
+        classpath="${common.basedir}/lib/build/jarjar-1.1.jar"/>
+    <jarjar jarfile="${build.dir}/${ant.project.name}-${version}-tests.jar">
+      <fileset dir="${build.dir}/test"/>
+      <rule pattern="net.sf.cglib.*" result="com.google.inject.internal.cglib.$@1"/>
+      <rule pattern="net.sf.cglib.**.*" result="com.google.inject.internal.cglib.@1.$@2"/>
+      <rule pattern="org.objectweb.asm.*" result="com.google.inject.internal.asm.$@1"/>
+      <rule pattern="org.objectweb.asm.**.*" result="com.google.inject.internal.asm.@1.$@2"/>
+      <keep pattern="com.google.inject.**"/>
+      <keep pattern="com.googlecode.**"/>
+    </jarjar>
+  </target>
+
+  <target name="jar.withdeps" depends="compile"
+      description="Build jar with dependencies embedded.">
+    <mkdir dir="${build.dir}/dist"/>
+    <dirname property="common.basedir" file="${ant.file.common}"/>
+    <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask"
+        classpath="${common.basedir}/lib/build/jarjar-1.1.jar"/>
+    <jarjar jarfile="${build.dir}/${ant.project.name}-with-deps.jar">
+      <fileset dir="${build.dir}/classes"/>
+      <zipfileset src="${common.basedir}/lib/build/cglib-3.1.jar"/>
+      <zipfileset src="${common.basedir}/lib/build/asm-5.0.3.jar"/>
+      <rule pattern="net.sf.cglib.*" result="com.google.inject.internal.cglib.$@1"/>
+      <rule pattern="net.sf.cglib.**.*" result="com.google.inject.internal.cglib.@1.$@2"/>
+      <rule pattern="org.objectweb.asm.*" result="com.google.inject.internal.asm.$@1"/>
+      <rule pattern="org.objectweb.asm.**.*" result="com.google.inject.internal.asm.@1.$@2"/>
+      <keep pattern="com.google.inject.**"/>
+    </jarjar>
+  </target>
+</project>
diff --git a/core/pom.xml b/core/pom.xml
new file mode 100644
index 0000000..5a11a23
--- /dev/null
+++ b/core/pom.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject</groupId>
+    <artifactId>guice-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice</artifactId>
+
+  <name>Google Guice - Core Library</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>javax.inject</groupId>
+      <artifactId>javax.inject</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>aopalliance</groupId>
+      <artifactId>aopalliance</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <!--
+     | CGLIB is embedded by default by the JarJar build profile
+    -->
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <!--
+     | Test dependencies
+    -->
+    <dependency>
+      <groupId>javax.inject</groupId>
+      <artifactId>javax.inject-tck</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava-testlib</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
+      <version>3.0.5.RELEASE</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>biz.aQute</groupId>
+      <artifactId>bnd</artifactId>
+      <version>0.0.384</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.framework</artifactId>
+      <version>3.0.5</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!--
+       | Add standard LICENSE and NOTICE files
+      -->
+      <plugin>
+        <artifactId>maven-remote-resources-plugin</artifactId>
+      </plugin>
+      <!--
+       | Enable Java6 conformance checks
+      -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>animal-sniffer-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <!--
+           | Temporarily excluded tests
+          -->
+          <excludes>
+            <exclude>**/*$*</exclude>
+            <exclude>**/ErrorHandlingTest*</exclude>
+            <exclude>**/OSGiContainerTest*</exclude>
+            <exclude>**/ScopesTest*</exclude>
+            <exclude>**/TypeConversionTest*</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+      <!--
+       | Add OSGi manifest
+      -->
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Bundle-Name>${project.artifactId}$(if;$(classes;NAMED;*.MethodAspect);; (no_aop))</Bundle-Name>
+            <Import-Package>!net.sf.cglib.*,!org.objectweb.asm.*,!com.google.inject.*,*</Import-Package>
+            <Eclipse-ExtensibleAPI>true</Eclipse-ExtensibleAPI>
+          </instructions>
+        </configuration>
+      </plugin>
+      <!--
+       | Remove duplicate jarjar'd LICENSE and NOTICE
+      -->
+      <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>LICENSE</exclude>
+            <exclude>NOTICE</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+      <!--
+       | Generate sources jar
+      -->
+      <plugin>
+        <artifactId>maven-source-plugin</artifactId>
+      </plugin>
+      <!--
+       | Generate javadoc jar
+      -->
+      <plugin>
+        <artifactId>maven-javadoc-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <!--
+       | No-AOP profile: repeat the build lifecycle with munged no-AOP source
+      -->
+      <id>guice.with.no_aop</id>
+      <activation>
+        <property>
+          <name>guice.with.no_aop</name>
+          <value>!false</value>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.sonatype.plugins</groupId>
+            <artifactId>munge-maven-plugin</artifactId>
+            <version>1.0</version>
+            <executions>
+              <execution>
+                <phase>prepare-package</phase>
+                <goals>
+                  <goal>munge-fork</goal>
+                </goals>
+                <configuration>
+                  <symbols>NO_AOP</symbols>
+                  <excludes>
+                    **/InterceptorBinding.java,
+                    **/InterceptorBindingProcessor.java,
+                    **/InterceptorStackCallback.java,
+                    **/LineNumbers.java,
+                    **/MethodAspect.java,
+                    **/ProxyFactory.java,
+                    **/BytecodeGenTest.java,
+                    **/IntegrationTest.java,
+                    **/MethodInterceptionTest.java,
+                    **/ProxyFactoryTest.java
+                  </excludes>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+          <!--
+           | Package the no-AOP build with its own OSGi manifest and attach using "no_aop" classifier
+          -->
+          <plugin>
+            <artifactId>maven-jar-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>no_aop</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+                <configuration>
+                  <classesDirectory>${project.build.directory}/munged/classes</classesDirectory>
+                  <classifier>no_aop</classifier>
+                  <archive>
+                    <manifestFile>${project.build.directory}/munged/classes/META-INF/MANIFEST.MF</manifestFile>
+                  </archive>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <!--
+       | JarJar build profile: Embed CGLIB (and ASM) classes under a Guice namespace
+      -->
+      <id>guice.with.jarjar</id>
+      <activation>
+        <property>
+          <name>guice.with.jarjar</name>
+          <value>!false</value>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.sonatype.plugins</groupId>
+            <artifactId>jarjar-maven-plugin</artifactId>
+            <version>1.9</version>
+            <executions>
+              <execution>
+                <id>jarjar</id>
+                <goals><goal>jarjar</goal></goals>
+              </execution>
+            </executions>
+            <configuration>
+              <overwrite>true</overwrite>
+              <includes>
+                <include>*:asm*</include>
+                <include>*:cglib</include>
+              </includes>
+              <rules>
+                <rule>
+                  <pattern>net.sf.cglib.*</pattern>
+                  <result>com.google.inject.internal.cglib.$@1</result>
+                </rule>
+                <rule>
+                  <pattern>net.sf.cglib.**.*</pattern>
+                  <result>com.google.inject.internal.cglib.@1.$@2</result>
+                </rule>
+                <rule>
+                  <pattern>org.objectweb.asm.*</pattern>
+                  <result>com.google.inject.internal.asm.$@1</result>
+                </rule>
+                <rule>
+                  <pattern>org.objectweb.asm.**.*</pattern>
+                  <result>com.google.inject.internal.asm.@1.$@2</result>
+                </rule>
+                <keep>
+                  <pattern>com.google.inject.**</pattern>
+                </keep>
+                <keep>
+                  <pattern>com.googlecode.**</pattern>
+                </keep>
+              </rules>
+            </configuration>
+          </plugin>
+          <plugin>
+            <!--
+             | Attach the original non-JarJar'd classes so extensions can compile against them
+            -->
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>build-helper-maven-plugin</artifactId>
+            <version>1.8</version>
+            <executions>
+              <execution>
+                <id>classes</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>attach-artifact</goal>
+                </goals>
+                <configuration>
+                  <artifacts>
+                    <artifact>
+                      <file>${project.build.directory}/original-${project.build.finalName}.jar</file>
+                      <classifier>classes</classifier>
+                    </artifact>
+                  </artifacts>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <!--
+       | m2e profile - enable use of JarJar inside Eclipse
+      -->
+      <id>m2e</id>
+      <activation>
+        <property>
+          <name>m2e.version</name>
+        </property>
+      </activation>
+      <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>org.eclipse.m2e</groupId>
+              <artifactId>lifecycle-mapping</artifactId>
+              <version>1.0.0</version>
+              <configuration>
+                <lifecycleMappingMetadata>
+                  <pluginExecutions>
+                    <pluginExecution>
+                      <pluginExecutionFilter>
+                        <groupId>org.sonatype.plugins</groupId>
+                        <artifactId>jarjar-maven-plugin</artifactId>
+                        <versionRange>[1.4,)</versionRange>
+                        <goals><goal>jarjar</goal></goals>
+                      </pluginExecutionFilter>
+                      <action><execute /></action>
+                    </pluginExecution>
+                  </pluginExecutions>
+                </lifecycleMappingMetadata>
+              </configuration>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/core/src/com/google/inject/AbstractModule.java b/core/src/com/google/inject/AbstractModule.java
new file mode 100644
index 0000000..fafbd12
--- /dev/null
+++ b/core/src/com/google/inject/AbstractModule.java
@@ -0,0 +1,266 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.AnnotatedConstantBindingBuilder;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.ProvisionListener;
+import com.google.inject.spi.TypeConverter;
+import com.google.inject.spi.TypeListener;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * A support class for {@link Module}s which reduces repetition and results in
+ * a more readable configuration. Simply extend this class, implement {@link
+ * #configure()}, and call the inherited methods which mirror those found in
+ * {@link Binder}. For example:
+ *
+ * <pre>
+ * public class MyModule extends AbstractModule {
+ *   protected void configure() {
+ *     bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
+ *     bind(CreditCardPaymentService.class);
+ *     bind(PaymentService.class).to(CreditCardPaymentService.class);
+ *     bindConstant().annotatedWith(Names.named("port")).to(8080);
+ *   }
+ * }
+ * </pre>
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public abstract class AbstractModule implements Module {
+
+  Binder binder;
+
+  public final synchronized void configure(Binder builder) {
+    checkState(this.binder == null, "Re-entry is not allowed.");
+
+    this.binder = checkNotNull(builder, "builder");
+    try {
+      configure();
+    }
+    finally {
+      this.binder = null;
+    }
+  }
+
+  /**
+   * Configures a {@link Binder} via the exposed methods.
+   */
+  protected abstract void configure();
+
+  /**
+   * Gets direct access to the underlying {@code Binder}.
+   */
+  protected Binder binder() {
+    checkState(binder != null, "The binder can only be used inside configure()");
+    return binder;
+  }
+
+  /**
+   * @see Binder#bindScope(Class, Scope)
+   */
+  protected void bindScope(Class<? extends Annotation> scopeAnnotation,
+      Scope scope) {
+    binder().bindScope(scopeAnnotation, scope);
+  }
+
+  /**
+   * @see Binder#bind(Key)
+   */
+  protected <T> LinkedBindingBuilder<T> bind(Key<T> key) {
+    return binder().bind(key);
+  }
+
+  /**
+   * @see Binder#bind(TypeLiteral)
+   */
+  protected <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
+    return binder().bind(typeLiteral);
+  }
+
+  /**
+   * @see Binder#bind(Class)
+   */
+  protected <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) {
+    return binder().bind(clazz);
+  }
+
+  /**
+   * @see Binder#bindConstant()
+   */
+  protected AnnotatedConstantBindingBuilder bindConstant() {
+    return binder().bindConstant();
+  }
+
+  /**
+   * @see Binder#install(Module)
+   */
+  protected void install(Module module) {
+    binder().install(module);
+  }
+
+  /**
+   * @see Binder#addError(String, Object[])
+   */
+  protected void addError(String message, Object... arguments) {
+    binder().addError(message, arguments);
+  }
+
+  /**
+   * @see Binder#addError(Throwable) 
+   */
+  protected void addError(Throwable t) {
+    binder().addError(t);
+  }
+
+  /**
+   * @see Binder#addError(Message)
+   * @since 2.0
+   */
+  protected void addError(Message message) {
+    binder().addError(message);
+  }
+
+  /**
+   * @see Binder#requestInjection(Object)
+   * @since 2.0
+   */
+  protected void requestInjection(Object instance) {
+    binder().requestInjection(instance);
+  }
+
+  /**
+   * @see Binder#requestStaticInjection(Class[])
+   */
+  protected void requestStaticInjection(Class<?>... types) {
+    binder().requestStaticInjection(types);
+  }
+
+  /*if[AOP]*/
+  /**
+   * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher,
+   *  com.google.inject.matcher.Matcher,
+   *  org.aopalliance.intercept.MethodInterceptor[])
+   */
+  protected void bindInterceptor(Matcher<? super Class<?>> classMatcher,
+      Matcher<? super Method> methodMatcher,
+      org.aopalliance.intercept.MethodInterceptor... interceptors) {
+    binder().bindInterceptor(classMatcher, methodMatcher, interceptors);
+  }
+  /*end[AOP]*/
+
+  /**
+   * Adds a dependency from this module to {@code key}. When the injector is
+   * created, Guice will report an error if {@code key} cannot be injected.
+   * Note that this requirement may be satisfied by implicit binding, such as
+   * a public no-arguments constructor.
+   *
+   * @since 2.0
+   */
+  protected void requireBinding(Key<?> key) {
+    binder().getProvider(key);
+  }
+
+  /**
+   * Adds a dependency from this module to {@code type}. When the injector is
+   * created, Guice will report an error if {@code type} cannot be injected.
+   * Note that this requirement may be satisfied by implicit binding, such as
+   * a public no-arguments constructor.
+   *
+   * @since 2.0
+   */
+  protected void requireBinding(Class<?> type) {
+    binder().getProvider(type);
+  }
+
+  /**
+   * @see Binder#getProvider(Key)
+   * @since 2.0
+   */
+  protected <T> Provider<T> getProvider(Key<T> key) {
+    return binder().getProvider(key);
+  }
+
+  /**
+   * @see Binder#getProvider(Class)
+   * @since 2.0
+   */
+  protected <T> Provider<T> getProvider(Class<T> type) {
+    return binder().getProvider(type);
+  }
+
+  /**
+   * @see Binder#convertToTypes
+   * @since 2.0
+   */
+  protected void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
+      TypeConverter converter) {
+    binder().convertToTypes(typeMatcher, converter);
+  }
+
+  /**
+   * @see Binder#currentStage() 
+   * @since 2.0
+   */
+  protected Stage currentStage() {
+    return binder().currentStage();
+  }
+
+  /**
+   * @see Binder#getMembersInjector(Class)
+   * @since 2.0
+   */
+  protected <T> MembersInjector<T> getMembersInjector(Class<T> type) {
+    return binder().getMembersInjector(type);
+  }
+
+  /**
+   * @see Binder#getMembersInjector(TypeLiteral)
+   * @since 2.0
+   */
+  protected <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> type) {
+    return binder().getMembersInjector(type);
+  }
+
+  /**
+   * @see Binder#bindListener(com.google.inject.matcher.Matcher,
+   *  com.google.inject.spi.TypeListener)
+   * @since 2.0
+   */
+  protected void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher,
+      TypeListener listener) {
+    binder().bindListener(typeMatcher, listener);
+  }
+  
+  /**
+   * @see Binder#bindListener(Matcher, ProvisionListener...)
+   * @since 4.0
+   */
+  protected void bindListener(Matcher<? super Binding<?>> bindingMatcher,
+      ProvisionListener... listener) {
+    binder().bindListener(bindingMatcher, listener);
+  }
+}
diff --git a/core/src/com/google/inject/Binder.java b/core/src/com/google/inject/Binder.java
new file mode 100644
index 0000000..e930c3b
--- /dev/null
+++ b/core/src/com/google/inject/Binder.java
@@ -0,0 +1,522 @@
+/*
+ * 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 com.google.inject;
+
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.AnnotatedConstantBindingBuilder;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.ModuleAnnotatedMethodScanner;
+import com.google.inject.spi.ProvisionListener;
+import com.google.inject.spi.TypeConverter;
+import com.google.inject.spi.TypeListener;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * Collects configuration information (primarily <i>bindings</i>) which will be
+ * used to create an {@link Injector}. Guice provides this object to your
+ * application's {@link Module} implementors so they may each contribute
+ * their own bindings and other registrations.
+ *
+ * <h3>The Guice Binding EDSL</h3>
+ *
+ * Guice uses an <i>embedded domain-specific language</i>, or EDSL, to help you
+ * create bindings simply and readably.  This approach is great for overall
+ * usability, but it does come with a small cost: <b>it is difficult to
+ * learn how to use the Binding EDSL by reading
+ * method-level javadocs</b>.  Instead, you should consult the series of
+ * examples below.  To save space, these examples omit the opening
+ * {@code binder}, just as you will if your module extends
+ * {@link AbstractModule}.
+ *
+ * <pre>
+ *     bind(ServiceImpl.class);</pre>
+ *
+ * This statement does essentially nothing; it "binds the {@code ServiceImpl}
+ * class to itself" and does not change Guice's default behavior.  You may still
+ * want to use this if you prefer your {@link Module} class to serve as an
+ * explicit <i>manifest</i> for the services it provides.  Also, in rare cases,
+ * Guice may be unable to validate a binding at injector creation time unless it
+ * is given explicitly.
+ *
+ * <pre>
+ *     bind(Service.class).to(ServiceImpl.class);</pre>
+ *
+ * Specifies that a request for a {@code Service} instance with no binding
+ * annotations should be treated as if it were a request for a
+ * {@code ServiceImpl} instance. This <i>overrides</i> the function of any
+ * {@link ImplementedBy @ImplementedBy} or {@link ProvidedBy @ProvidedBy}
+ * annotations found on {@code Service}, since Guice will have already
+ * "moved on" to {@code ServiceImpl} before it reaches the point when it starts
+ * looking for these annotations.
+ *
+ * <pre>
+ *     bind(Service.class).toProvider(ServiceProvider.class);</pre>
+ *
+ * In this example, {@code ServiceProvider} must extend or implement
+ * {@code Provider<Service>}. This binding specifies that Guice should resolve
+ * an unannotated injection request for {@code Service} by first resolving an
+ * instance of {@code ServiceProvider} in the regular way, then calling
+ * {@link Provider#get get()} on the resulting Provider instance to obtain the
+ * {@code Service} instance.
+ *
+ * <p>The {@link Provider} you use here does not have to be a "factory"; that
+ * is, a provider which always <i>creates</i> each instance it provides.
+ * However, this is generally a good practice to follow.  You can then use
+ * Guice's concept of {@link Scope scopes} to guide when creation should happen
+ * -- "letting Guice work for you".
+ *
+ * <pre>
+ *     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);</pre>
+ *
+ * Like the previous example, but only applies to injection requests that use
+ * the binding annotation {@code @Red}.  If your module also includes bindings
+ * for particular <i>values</i> of the {@code @Red} annotation (see below),
+ * then this binding will serve as a "catch-all" for any values of {@code @Red}
+ * that have no exact match in the bindings.
+ * 
+ * <pre>
+ *     bind(ServiceImpl.class).in(Singleton.class);
+ *     // or, alternatively
+ *     bind(ServiceImpl.class).in(Scopes.SINGLETON);</pre>
+ *
+ * Either of these statements places the {@code ServiceImpl} class into
+ * singleton scope.  Guice will create only one instance of {@code ServiceImpl}
+ * and will reuse it for all injection requests of this type.  Note that it is
+ * still possible to bind another instance of {@code ServiceImpl} if the second
+ * binding is qualified by an annotation as in the previous example.  Guice is
+ * not overly concerned with <i>preventing</i> you from creating multiple
+ * instances of your "singletons", only with <i>enabling</i> your application to
+ * share only one instance if that's all you tell Guice you need.
+ *
+ * <p><b>Note:</b> a scope specified in this way <i>overrides</i> any scope that
+ * was specified with an annotation on the {@code ServiceImpl} class.
+ * 
+ * <p>Besides {@link Singleton}/{@link Scopes#SINGLETON}, there are
+ * servlet-specific scopes available in
+ * {@code com.google.inject.servlet.ServletScopes}, and your Modules can
+ * contribute their own custom scopes for use here as well.
+ *
+ * <pre>
+ *     bind(new TypeLiteral&lt;PaymentService&lt;CreditCard>>() {})
+ *         .to(CreditCardPaymentService.class);</pre>
+ *
+ * This admittedly odd construct is the way to bind a parameterized type. It
+ * tells Guice how to honor an injection request for an element of type
+ * {@code PaymentService<CreditCard>}. The class
+ * {@code CreditCardPaymentService} must implement the
+ * {@code PaymentService<CreditCard>} interface.  Guice cannot currently bind or
+ * inject a generic type, such as {@code Set<E>}; all type parameters must be
+ * fully specified.
+ *
+ * <pre>
+ *     bind(Service.class).toInstance(new ServiceImpl());
+ *     // or, alternatively
+ *     bind(Service.class).toInstance(SomeLegacyRegistry.getService());</pre>
+ *
+ * In this example, your module itself, <i>not Guice</i>, takes responsibility
+ * for obtaining a {@code ServiceImpl} instance, then asks Guice to always use
+ * this single instance to fulfill all {@code Service} injection requests.  When
+ * the {@link Injector} is created, it will automatically perform field
+ * and method injection for this instance, but any injectable constructor on
+ * {@code ServiceImpl} is simply ignored.  Note that using this approach results
+ * in "eager loading" behavior that you can't control.
+ *
+ * <pre>
+ *     bindConstant().annotatedWith(ServerHost.class).to(args[0]);</pre>
+ *
+ * Sets up a constant binding. Constant injections must always be annotated.
+ * When a constant binding's value is a string, it is eligile for conversion to
+ * all primitive types, to {@link Enum#valueOf(Class, String) all enums}, and to
+ * {@link Class#forName class literals}. Conversions for other types can be
+ * configured using {@link #convertToTypes(Matcher, TypeConverter)
+ * convertToTypes()}.
+ *
+ * <pre>
+ *   {@literal @}Color("red") Color red; // A member variable (field)
+ *    . . .
+ *     red = MyModule.class.getDeclaredField("red").getAnnotation(Color.class);
+ *     bind(Service.class).annotatedWith(red).to(RedService.class);</pre>
+ *
+ * If your binding annotation has parameters you can apply different bindings to
+ * different specific values of your annotation.  Getting your hands on the
+ * right instance of the annotation is a bit of a pain -- one approach, shown
+ * above, is to apply a prototype annotation to a field in your module class, so
+ * that you can read this annotation instance and give it to Guice.
+ *
+ * <pre>
+ *     bind(Service.class)
+ *         .annotatedWith(Names.named("blue"))
+ *         .to(BlueService.class);</pre>
+ *
+ * Differentiating by names is a common enough use case that we provided a
+ * standard annotation, {@link com.google.inject.name.Named @Named}.  Because of
+ * Guice's library support, binding by name is quite easier than in the
+ * arbitrary binding annotation case we just saw.  However, remember that these
+ * names will live in a single flat namespace with all the other names used in
+ * your application.
+ *
+ * <pre>
+ *     Constructor<T> loneCtor = getLoneCtorFromServiceImplViaReflection();
+ *     bind(ServiceImpl.class)
+ *         .toConstructor(loneCtor);</pre>
+ *
+ * In this example, we directly tell Guice which constructor to use in a concrete
+ * class implementation. It means that we do not need to place {@literal @}Inject
+ * on any of the constructors and that Guice treats the provided constructor as though
+ * it were annotated so. It is useful for cases where you cannot modify existing
+ * classes and is a bit simpler than using a {@link Provider}.
+ *
+ * <p>The above list of examples is far from exhaustive.  If you can think of
+ * how the concepts of one example might coexist with the concepts from another,
+ * you can most likely weave the two together.  If the two concepts make no
+ * sense with each other, you most likely won't be able to do it.  In a few
+ * cases Guice will let something bogus slip by, and will then inform you of
+ * the problems at runtime, as soon as you try to create your Injector.
+ *
+ * <p>The other methods of Binder such as {@link #bindScope},
+ * {@link #bindInterceptor}, {@link #install}, {@link #requestStaticInjection},
+ * {@link #addError} and {@link #currentStage} are not part of the Binding EDSL;
+ * you can learn how to use these in the usual way, from the method
+ * documentation.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @author kevinb@google.com (Kevin Bourrillion)
+ */
+public interface Binder {
+
+  /*if[AOP]*/
+  /**
+   * Binds method interceptor[s] to methods matched by class and method matchers. A method is
+   * eligible for interception if:
+   *
+   * <ul>
+   *  <li>Guice created the instance the method is on</li>
+   *  <li>Neither the enclosing type nor the method is final</li>
+   *  <li>And the method is package-private, protected, or public</li>
+   * </ul>
+   *
+   * @param classMatcher matches classes the interceptor should apply to. For
+   *     example: {@code only(Runnable.class)}.
+   * @param methodMatcher matches methods the interceptor should apply to. For
+   *     example: {@code annotatedWith(Transactional.class)}.
+   * @param interceptors to bind.  The interceptors are called in the order they
+   *     are given.
+   */
+  void bindInterceptor(Matcher<? super Class<?>> classMatcher,
+      Matcher<? super Method> methodMatcher,
+      org.aopalliance.intercept.MethodInterceptor... interceptors);
+  /*end[AOP]*/
+
+  /**
+   * Binds a scope to an annotation.
+   */
+  void bindScope(Class<? extends Annotation> annotationType, Scope scope);
+
+  /**
+   * See the EDSL examples at {@link Binder}.
+   */
+  <T> LinkedBindingBuilder<T> bind(Key<T> key);
+
+  /**
+   * See the EDSL examples at {@link Binder}.
+   */
+  <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral);
+
+  /**
+   * See the EDSL examples at {@link Binder}.
+   */
+  <T> AnnotatedBindingBuilder<T> bind(Class<T> type);
+
+  /**
+   * See the EDSL examples at {@link Binder}.
+   */
+  AnnotatedConstantBindingBuilder bindConstant();
+
+  /**
+   * Upon successful creation, the {@link Injector} will inject instance fields
+   * and methods of the given object.
+   *
+   * @param type of instance
+   * @param instance for which members will be injected
+   * @since 2.0
+   */
+  <T> void requestInjection(TypeLiteral<T> type, T instance);
+
+  /**
+   * Upon successful creation, the {@link Injector} will inject instance fields
+   * and methods of the given object.
+   *
+   * @param instance for which members will be injected
+   * @since 2.0
+   */
+  void requestInjection(Object instance);
+
+  /**
+   * Upon successful creation, the {@link Injector} will inject static fields
+   * and methods in the given classes.
+   *
+   * @param types for which static members will be injected
+   */
+  void requestStaticInjection(Class<?>... types);
+
+  /**
+   * Uses the given module to configure more bindings.
+   */
+  void install(Module module);
+
+  /**
+   * Gets the current stage.
+   */
+  Stage currentStage();
+
+  /**
+   * Records an error message which will be presented to the user at a later
+   * time. Unlike throwing an exception, this enable us to continue
+   * configuring the Injector and discover more errors. Uses {@link
+   * String#format(String, Object[])} to insert the arguments into the
+   * message.
+   */
+  void addError(String message, Object... arguments);
+
+  /**
+   * Records an exception, the full details of which will be logged, and the
+   * message of which will be presented to the user at a later
+   * time. If your Module calls something that you worry may fail, you should
+   * catch the exception and pass it into this.
+   */
+  void addError(Throwable t);
+
+  /**
+   * Records an error message to be presented to the user at a later time.
+   *
+   * @since 2.0
+   */
+  void addError(Message message);
+
+  /**
+   * Returns the provider used to obtain instances for the given injection key.
+   * The returned provider will not be valid until the {@link Injector} has been
+   * created. The provider will throw an {@code IllegalStateException} if you
+   * try to use it beforehand.
+   *
+   * @since 2.0
+   */
+  <T> Provider<T> getProvider(Key<T> key);
+
+  /**
+   * Returns the provider used to obtain instances for the given injection key.
+   * The returned provider will be attached to the injection point and will
+   * follow the nullability specified in the dependency.
+   * Additionally, the returned provider will not be valid until the {@link Injector} 
+   * has been created. The provider will throw an {@code IllegalStateException} if you
+   * try to use it beforehand.
+   *
+   * @since 4.0
+   */
+  <T> Provider<T> getProvider(Dependency<T> dependency);
+
+  /**
+   * Returns the provider used to obtain instances for the given injection type.
+   * The returned provider will not be valid until the {@link Injector} has been
+   * created. The provider will throw an {@code IllegalStateException} if you
+   * try to use it beforehand.
+   *
+   * @since 2.0
+   */
+  <T> Provider<T> getProvider(Class<T> type);
+
+  /**
+   * Returns the members injector used to inject dependencies into methods and fields on instances
+   * of the given type {@code T}. The returned members injector will not be valid until the main
+   * {@link Injector} has been created. The members injector will throw an {@code
+   * IllegalStateException} if you try to use it beforehand.
+   *
+   * @param typeLiteral type to get members injector for
+   * @since 2.0
+   */
+  <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral);
+
+  /**
+   * Returns the members injector used to inject dependencies into methods and fields on instances
+   * of the given type {@code T}. The returned members injector will not be valid until the main
+   * {@link Injector} has been created. The members injector will throw an {@code
+   * IllegalStateException} if you try to use it beforehand.
+   *
+   * @param type type to get members injector for
+   * @since 2.0
+   */
+  <T> MembersInjector<T> getMembersInjector(Class<T> type);
+
+  /**
+   * Binds a type converter. The injector will use the given converter to
+   * convert string constants to matching types as needed.
+   *
+   * @param typeMatcher matches types the converter can handle
+   * @param converter converts values
+   * @since 2.0
+   */
+  void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
+      TypeConverter converter);
+
+  /**
+   * Registers a listener for injectable types. Guice will notify the listener when it encounters
+   * injectable types matched by the given type matcher.
+   *
+   * @param typeMatcher that matches injectable types the listener should be notified of
+   * @param listener for injectable types matched by typeMatcher
+   * @since 2.0
+   */
+  void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher,
+      TypeListener listener);
+
+  /**
+   * Registers listeners for provisioned objects. Guice will notify the
+   * listeners just before and after the object is provisioned. Provisioned
+   * objects that are also injectable (everything except objects provided
+   * through Providers) can also be notified through TypeListeners registered in
+   * {@link #bindListener}.
+   * 
+   * @param bindingMatcher that matches bindings of provisioned objects the listener
+   *          should be notified of
+   * @param listeners for provisioned objects matched by bindingMatcher 
+   * @since 4.0
+   */
+  void bindListener(Matcher<? super Binding<?>> bindingMatcher, ProvisionListener... listeners);
+
+  /**
+   * Returns a binder that uses {@code source} as the reference location for
+   * configuration errors. This is typically a {@link StackTraceElement}
+   * for {@code .java} source but it could any binding source, such as the
+   * path to a {@code .properties} file.
+   *
+   * @param source any object representing the source location and has a
+   *     concise {@link Object#toString() toString()} value
+   * @return a binder that shares its configuration with this binder
+   * @since 2.0
+   */
+  Binder withSource(Object source);
+
+  /**
+   * Returns a binder that skips {@code classesToSkip} when identify the
+   * calling code. The caller's {@link StackTraceElement} is used to locate
+   * the source of configuration errors.
+   *
+   * @param classesToSkip library classes that create bindings on behalf of
+   *      their clients.
+   * @return a binder that shares its configuration with this binder.
+   * @since 2.0
+   */
+  Binder skipSources(Class... classesToSkip);
+
+  /**
+   * Creates a new private child environment for bindings and other configuration. The returned
+   * binder can be used to add and configuration information in this environment. See {@link
+   * PrivateModule} for details.
+   *
+   * @return a binder that inherits configuration from this binder. Only exposed configuration on
+   *      the returned binder will be visible to this binder.
+   * @since 2.0
+   */
+  PrivateBinder newPrivateBinder();
+
+  /**
+   * Instructs the Injector that bindings must be listed in a Module in order to
+   * be injected. Classes that are not explicitly bound in a module cannot be
+   * injected. Bindings created through a linked binding
+   * (<code>bind(Foo.class).to(FooImpl.class)</code>) are allowed, but the
+   * implicit binding (<code>FooImpl</code>) cannot be directly injected unless
+   * it is also explicitly bound (<code>bind(FooImpl.class)</code>).
+   * <p>
+   * Tools can still retrieve bindings for implicit bindings (bindings created
+   * through a linked binding) if explicit bindings are required, however
+   * {@link Binding#getProvider} will fail.
+   * <p>
+   * By default, explicit bindings are not required.
+   * <p>
+   * If a parent injector requires explicit bindings, then all child injectors
+   * (and private modules within that injector) also require explicit bindings.
+   * If a parent does not require explicit bindings, a child injector or private
+   * module may optionally declare itself as requiring explicit bindings. If it
+   * does, the behavior is limited only to that child or any grandchildren. No
+   * siblings of the child will require explicit bindings.
+   * <p>
+   * In the absence of an explicit binding for the target, linked bindings in
+   * child injectors create a binding for the target in the parent. Since this
+   * behavior can be surprising, it causes an error instead if explicit bindings
+   * are required. To avoid this error, add an explicit binding for the target,
+   * either in the child or the parent.
+   * 
+   * @since 3.0
+   */
+  void requireExplicitBindings();
+  
+  /**
+   * Prevents Guice from constructing a {@link Proxy} when a circular dependency
+   * is found.  By default, circular proxies are not disabled.
+   * <p>
+   * If a parent injector disables circular proxies, then all child injectors
+   * (and private modules within that injector) also disable circular proxies.
+   * If a parent does not disable circular proxies, a child injector or private
+   * module may optionally declare itself as disabling circular proxies. If it
+   * does, the behavior is limited only to that child or any grandchildren. No
+   * siblings of the child will disable circular proxies.
+   * 
+   * @since 3.0
+   */
+  void disableCircularProxies();
+  
+  /**
+   * Requires that a {@literal @}{@link Inject} annotation exists on a constructor in order for
+   * Guice to consider it an eligible injectable class. By default, Guice will inject classes that
+   * have a no-args constructor if no {@literal @}{@link Inject} annotation exists on any
+   * constructor.
+   * <p>
+   * If the class is bound using {@link LinkedBindingBuilder#toConstructor}, Guice will still inject
+   * that constructor regardless of annotations.
+   *
+   * @since 4.0
+   */
+  void requireAtInjectOnConstructors();
+
+  /**
+   * Requires that Guice finds an exactly matching binding annotation.  This disables the
+   * error-prone feature in Guice where it can substitute a binding for
+   * <code>{@literal @}Named Foo</code> when attempting to inject
+   * <code>{@literal @}Named("foo") Foo</code>.
+   *
+   * @since 4.0
+   */
+  void requireExactBindingAnnotations();
+
+  /**
+   * Adds a scanner that will look in all installed modules for annotations the scanner can parse,
+   * and binds them like {@literal @}Provides methods. Scanners apply to all modules installed in
+   * the injector. Scanners installed in child injectors or private modules do not impact modules in
+   * siblings or parents, however scanners installed in parents do apply to all child injectors and
+   * private modules.
+   *
+   * @since 4.0
+   */
+  void scanModulesForAnnotatedMethods(ModuleAnnotatedMethodScanner scanner);
+}
diff --git a/core/src/com/google/inject/Binding.java b/core/src/com/google/inject/Binding.java
new file mode 100644
index 0000000..332237e
--- /dev/null
+++ b/core/src/com/google/inject/Binding.java
@@ -0,0 +1,92 @@
+/**
+ * Copyright (C) 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.inject;
+
+import com.google.inject.spi.BindingScopingVisitor;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Element;
+
+/**
+ * A mapping from a key (type and optional annotation) to the strategy for getting instances of the
+ * type. This interface is part of the introspection API and is intended primarily for use by 
+ * tools.
+ *
+ * <p>Bindings are created in several ways:
+ * <ul>
+ *     <li>Explicitly in a module, via {@code bind()} and {@code bindConstant()}
+ *         statements:
+ * <pre>
+ *     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);
+ *     bindConstant().annotatedWith(ServerHost.class).to(args[0]);</pre></li>
+ *     <li>Implicitly by the Injector by following a type's {@link ImplementedBy
+ *         pointer} {@link ProvidedBy annotations} or by using its {@link Inject annotated} or
+ *         default constructor.</li>
+ *     <li>By converting a bound instance to a different type.</li>
+ *     <li>For {@link Provider providers}, by delegating to the binding for the provided type.</li>
+ * </ul>
+ *
+ *
+ * <p>They exist on both modules and on injectors, and their behaviour is different for each:
+ * <ul>
+ *     <li><strong>Module bindings</strong> are incomplete and cannot be used to provide instances.
+ *         This is because the applicable scopes and interceptors may not be known until an injector
+ *         is created. From a tool's perspective, module bindings are like the injector's source
+ *         code. They can be inspected or rewritten, but this analysis must be done statically.</li>
+ *     <li><strong>Injector bindings</strong> are complete and valid and can be used to provide
+ *         instances. From a tools' perspective, injector bindings are like reflection for an
+ *         injector. They have full runtime information, including the complete graph of injections
+ *         necessary to satisfy a binding.</li>
+ * </ul>
+ *
+ * @param <T> the bound type. The injected is always assignable to this type.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public interface Binding<T> extends Element {
+
+  /**
+   * Returns the key for this binding.
+   */
+  Key<T> getKey();
+
+  /**
+   * Returns the scoped provider guice uses to fulfill requests for this
+   * binding.
+   *
+   * @throws UnsupportedOperationException when invoked on a {@link Binding}
+   *      created via {@link com.google.inject.spi.Elements#getElements}. This
+   *      method is only supported on {@link Binding}s returned from an injector.
+   */
+  Provider<T> getProvider();
+
+  /**
+   * Accepts a target visitor. Invokes the visitor method specific to this binding's target.
+   *
+   * @param visitor to call back on
+   * @since 2.0
+   */
+  <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor);
+
+  /**
+   * Accepts a scoping visitor. Invokes the visitor method specific to this binding's scoping.
+   *
+   * @param visitor to call back on
+   * @since 2.0
+   */
+  <V> V acceptScopingVisitor(BindingScopingVisitor<V> visitor);
+}
diff --git a/core/src/com/google/inject/BindingAnnotation.java b/core/src/com/google/inject/BindingAnnotation.java
new file mode 100644
index 0000000..2d373e4
--- /dev/null
+++ b/core/src/com/google/inject/BindingAnnotation.java
@@ -0,0 +1,41 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates annotations which are used for binding. Only one such annotation
+ * may apply to a single injection point. You must also annotate binder
+ * annotations with {@code @Retention(RUNTIME)}. For example:
+ *
+ * <pre>
+ *   {@code @}Retention(RUNTIME)
+ *   {@code @}Target({ FIELD, PARAMETER, METHOD })
+ *   {@code @}BindingAnnotation
+ *   public {@code @}interface Transactional {}
+ * </pre>
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Target(ANNOTATION_TYPE)
+@Retention(RUNTIME)
+public @interface BindingAnnotation {}
diff --git a/core/src/com/google/inject/ConfigurationException.java b/core/src/com/google/inject/ConfigurationException.java
new file mode 100644
index 0000000..e298cff
--- /dev/null
+++ b/core/src/com/google/inject/ConfigurationException.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.internal.Errors;
+import com.google.inject.spi.Message;
+
+import java.util.Collection;
+
+/**
+ * Thrown when a programming error such as a misplaced annotation, illegal binding, or unsupported
+ * scope is found. Clients should catch this exception, log it, and stop execution.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class ConfigurationException extends RuntimeException {
+
+  private final ImmutableSet<Message> messages;
+  private Object partialValue = null;
+
+  /** Creates a ConfigurationException containing {@code messages}. */
+  public ConfigurationException(Iterable<Message> messages) {
+    this.messages = ImmutableSet.copyOf(messages); 
+    initCause(Errors.getOnlyCause(this.messages));
+  }
+
+  /** Returns a copy of this configuration exception with the specified partial value. */
+  public ConfigurationException withPartialValue(Object partialValue) {
+    checkState(this.partialValue == null,
+        "Can't clobber existing partial value %s with %s", this.partialValue, partialValue);
+    ConfigurationException result = new ConfigurationException(messages);
+    result.partialValue = partialValue;
+    return result;
+  }
+
+  /** Returns messages for the errors that caused this exception. */
+  public Collection<Message> getErrorMessages() {
+    return messages;
+  }
+
+  /**
+   * Returns a value that was only partially computed due to this exception. The caller can use
+   * this while collecting additional configuration problems.
+   *
+   * @return the partial value, or {@code null} if none was set. The type of the partial value is
+   *      specified by the throwing method.
+   */
+  @SuppressWarnings("unchecked") // this is *extremely* unsafe. We trust the caller here.
+  public <E> E getPartialValue() {
+    return (E) partialValue;
+  }
+
+  @Override public String getMessage() {
+    return Errors.format("Guice configuration errors", messages);
+  }
+
+  private static final long serialVersionUID = 0;
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/CreationException.java b/core/src/com/google/inject/CreationException.java
new file mode 100644
index 0000000..4f84c22
--- /dev/null
+++ b/core/src/com/google/inject/CreationException.java
@@ -0,0 +1,54 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.internal.Errors;
+import com.google.inject.spi.Message;
+
+import java.util.Collection;
+
+/**
+ * Thrown when errors occur while creating a {@link Injector}. Includes a list of encountered
+ * errors. Clients should catch this exception, log it, and stop execution.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class CreationException extends RuntimeException {
+
+  private final ImmutableSet<Message> messages;
+
+  /** Creates a CreationException containing {@code messages}. */
+  public CreationException(Collection<Message> messages) {
+    this.messages = ImmutableSet.copyOf(messages);
+    checkArgument(!this.messages.isEmpty());
+    initCause(Errors.getOnlyCause(this.messages));
+  }
+
+  /** Returns messages for the errors that caused this exception. */
+  public Collection<Message> getErrorMessages() {
+    return messages;
+  }
+
+  @Override public String getMessage() {
+    return Errors.format("Unable to create injector, see the following errors", messages);
+  }
+
+  private static final long serialVersionUID = 0;
+}
diff --git a/core/src/com/google/inject/Exposed.java b/core/src/com/google/inject/Exposed.java
new file mode 100644
index 0000000..45a448f
--- /dev/null
+++ b/core/src/com/google/inject/Exposed.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Acccompanies a {@literal @}{@link com.google.inject.Provides Provides} method annotation in a
+ * private module to indicate that the provided binding is exposed.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+@Target(ElementType.METHOD) @Retention(RUNTIME) @Documented
+public @interface Exposed {}
diff --git a/core/src/com/google/inject/Guice.java b/core/src/com/google/inject/Guice.java
new file mode 100644
index 0000000..703187f
--- /dev/null
+++ b/core/src/com/google/inject/Guice.java
@@ -0,0 +1,101 @@
+/*
+ * 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 com.google.inject;
+
+import com.google.inject.internal.InternalInjectorCreator;
+
+import java.util.Arrays;
+
+/**
+ * The entry point to the Guice framework. Creates {@link Injector}s from
+ * {@link Module}s.
+ *
+ * <p>Guice supports a model of development that draws clear boundaries between
+ * APIs, Implementations of these APIs, Modules which configure these
+ * implementations, and finally Applications which consist of a collection of
+ * Modules. It is the Application, which typically defines your {@code main()}
+ * method, that bootstraps the Guice Injector using the {@code Guice} class, as
+ * in this example:
+ * <pre>
+ *     public class FooApplication {
+ *       public static void main(String[] args) {
+ *         Injector injector = Guice.createInjector(
+ *             new ModuleA(),
+ *             new ModuleB(),
+ *             . . .
+ *             new FooApplicationFlagsModule(args)
+ *         );
+ *
+ *         // Now just bootstrap the application and you're done
+ *         FooStarter starter = injector.getInstance(FooStarter.class);
+ *         starter.runApplication();
+ *       }
+ *     }
+ * </pre>
+ */
+public final class Guice {
+
+  private Guice() {}
+
+  /**
+   * Creates an injector for the given set of modules. This is equivalent to
+   * calling {@link #createInjector(Stage, Module...)} with Stage.DEVELOPMENT.
+   *
+   * @throws CreationException if one or more errors occur during injector
+   *     construction
+   */
+  public static Injector createInjector(Module... modules) {
+    return createInjector(Arrays.asList(modules));
+  }
+
+  /**
+   * Creates an injector for the given set of modules. This is equivalent to
+   * calling {@link #createInjector(Stage, Iterable)} with Stage.DEVELOPMENT.
+   *
+   * @throws CreationException if one or more errors occur during injector
+   *     creation
+   */
+  public static Injector createInjector(Iterable<? extends Module> modules) {
+    return createInjector(Stage.DEVELOPMENT, modules);
+  }
+
+  /**
+   * Creates an injector for the given set of modules, in a given development
+   * stage.
+   *
+   * @throws CreationException if one or more errors occur during injector
+   *     creation.
+   */
+  public static Injector createInjector(Stage stage, Module... modules) {
+    return createInjector(stage, Arrays.asList(modules));
+  }
+
+  /**
+   * Creates an injector for the given set of modules, in a given development
+   * stage.
+   *
+   * @throws CreationException if one or more errors occur during injector
+   *     construction
+   */
+  public static Injector createInjector(Stage stage,
+      Iterable<? extends Module> modules) {
+    return new InternalInjectorCreator()
+        .stage(stage)
+        .addModules(modules)
+        .build();
+  }
+}
diff --git a/core/src/com/google/inject/ImplementedBy.java b/core/src/com/google/inject/ImplementedBy.java
new file mode 100644
index 0000000..464a279
--- /dev/null
+++ b/core/src/com/google/inject/ImplementedBy.java
@@ -0,0 +1,38 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * A pointer to the default implementation of a type.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Retention(RUNTIME)
+@Target(TYPE)
+public @interface ImplementedBy {
+
+  /**
+   * The implementation type.
+   */
+  Class<?> value();
+}
diff --git a/core/src/com/google/inject/Inject.java b/core/src/com/google/inject/Inject.java
new file mode 100644
index 0000000..535c0a4
--- /dev/null
+++ b/core/src/com/google/inject/Inject.java
@@ -0,0 +1,69 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates members of your implementation class (constructors, methods
+ * and fields) into which the {@link Injector} should inject values.
+ * The Injector fulfills injection requests for:
+ *
+ * <ul>
+ * <li>Every instance it constructs. The class being constructed must have
+ * exactly one of its constructors marked with {@code @Inject} or must have a
+ * constructor taking no parameters. The Injector then proceeds to perform
+ * field and method injections.
+ * 
+ * <li>Pre-constructed instances passed to {@link Injector#injectMembers},
+ * {@link com.google.inject.binder.LinkedBindingBuilder#toInstance(Object)} and
+ * {@link com.google.inject.binder.LinkedBindingBuilder#toProvider(javax.inject.Provider)}.
+ * In this case all constructors are, of course, ignored.
+ *
+ * <li>Static fields and methods of classes which any {@link Module} has
+ * specifically requested static injection for, using
+ * {@link Binder#requestStaticInjection}.
+ * </ul>
+ *
+ * In all cases, a member can be injected regardless of its Java access
+ * specifier (private, default, protected, public).
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Target({ METHOD, CONSTRUCTOR, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface Inject {
+
+  /**
+   * If true, and the appropriate binding is not found,
+   * the Injector will skip injection of this method or field rather than
+   * produce an error. When applied to a field, any default value already
+   * assigned to the field will remain (guice will not actively null out the
+   * field). When applied to a method, the method will only be invoked if
+   * bindings for <i>all</i> parameters are found. When applied to a
+   * constructor, an error will result upon Injector creation.
+   */
+  boolean optional() default false;
+}
diff --git a/core/src/com/google/inject/Injector.java b/core/src/com/google/inject/Injector.java
new file mode 100644
index 0000000..42c7331
--- /dev/null
+++ b/core/src/com/google/inject/Injector.java
@@ -0,0 +1,265 @@
+/**
+ * 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 com.google.inject;
+
+import com.google.inject.spi.TypeConverterBinding;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Builds the graphs of objects that make up your application. The injector tracks the dependencies
+ * for each type and uses bindings to inject them. This is the core of Guice, although you rarely
+ * interact with it directly. This "behind-the-scenes" operation is what distinguishes dependency
+ * injection from its cousin, the service locator pattern.
+ *
+ * <p>Contains several default bindings:
+ *
+ * <ul>
+ * <li>This {@link Injector} instance itself
+ * <li>A {@code Provider<T>} for each binding of type {@code T}
+ * <li>The {@link java.util.logging.Logger} for the class being injected
+ * <li>The {@link Stage} in which the Injector was created
+ * </ul>
+ *
+ * Injectors are created using the facade class {@link Guice}.
+ *
+ * <p>An injector can also {@link #injectMembers(Object) inject the dependencies} of
+ * already-constructed instances. This can be used to interoperate with objects created by other
+ * frameworks or services.
+ *
+ * <p>Injectors can be {@link #createChildInjector(Iterable) hierarchical}. Child injectors inherit
+ * the configuration of their parent injectors, but the converse does not hold.
+ *
+ * <p>The injector's {@link #getBindings() internal bindings} are available for introspection. This
+ * enables tools and extensions to operate on an injector reflectively.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public interface Injector {
+
+  /**
+   * Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
+   * absence of an injectable constructor.
+   *
+   * <p>Whenever Guice creates an instance, it performs this injection automatically (after first
+   * performing constructor injection), so if you're able to let Guice create all your objects for
+   * you, you'll never need to use this method.
+   *
+   * @param instance to inject members on
+   *
+   * @see Binder#getMembersInjector(Class) for a preferred alternative that supports checks before
+   *  run time
+   */
+  void injectMembers(Object instance);
+
+  /**
+   * Returns the members injector used to inject dependencies into methods and fields on instances
+   * of the given type {@code T}.
+   *
+   * @param typeLiteral type to get members injector for
+   * @see Binder#getMembersInjector(TypeLiteral) for an alternative that offers up front error
+   *  detection
+   * @since 2.0
+   */
+  <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral);
+
+  /**
+   * Returns the members injector used to inject dependencies into methods and fields on instances
+   * of the given type {@code T}. When feasible, use {@link Binder#getMembersInjector(TypeLiteral)}
+   * instead to get increased up front error detection.
+   *
+   * @param type type to get members injector for
+   * @see Binder#getMembersInjector(Class) for an alternative that offers up front error
+   *  detection
+   * @since 2.0
+   */
+  <T> MembersInjector<T> getMembersInjector(Class<T> type);
+
+  /**
+   * Returns this injector's <strong>explicit</strong> bindings.
+   *
+   * <p>The returned map does not include bindings inherited from a {@link #getParent() parent
+   * injector}, should one exist. The returned map is guaranteed to iterate (for example, with
+   * its {@link Map#entrySet()} iterator) in the order of insertion. In other words, the order in
+   * which bindings appear in user Modules.
+   *
+   * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+   */
+  Map<Key<?>, Binding<?>> getBindings();
+
+  /**
+   * Returns a snapshot of this injector's bindings, <strong>both explicit and
+   * just-in-time</strong>. The returned map is immutable; it contains only the bindings that were
+   * present when {@code getAllBindings()} was invoked. Subsequent calls may return a map with
+   * additional just-in-time bindings.
+   *
+   * <p>The returned map does not include bindings inherited from a {@link #getParent() parent
+   * injector}, should one exist.
+   *
+   * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+   * 
+   * @since 3.0
+   */
+  Map<Key<?>, Binding<?>> getAllBindings();
+
+  /**
+   * Returns the binding for the given injection key. This will be an explicit bindings if the key
+   * was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
+   * be created if necessary.
+   *
+   * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+   *
+   * @throws ConfigurationException if this injector cannot find or create the binding.
+   */
+  <T> Binding<T> getBinding(Key<T> key);
+
+  /**
+   * Returns the binding for the given type. This will be an explicit bindings if the injection key
+   * was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
+   * be created if necessary.
+   *
+   * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+   *
+   * @throws ConfigurationException if this injector cannot find or create the binding.
+   * @since 2.0
+   */
+  <T> Binding<T> getBinding(Class<T> type);
+  
+  /**
+   * Returns the binding if it already exists, or null if does not exist. Unlike
+   * {@link #getBinding(Key)}, this does not attempt to create just-in-time bindings
+   * for keys that aren't bound.
+   * 
+   * <p> This method is part of the Guice SPI and is intended for use by tools and extensions.
+   * 
+   * @since 3.0
+   */
+  <T> Binding<T> getExistingBinding(Key<T> key);  
+
+  /**
+   * Returns all explicit bindings for {@code type}.
+   *
+   * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+   */
+  <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type);
+
+  /**
+   * Returns the provider used to obtain instances for the given injection key. When feasible, avoid
+   * using this method, in favor of having Guice inject your dependencies ahead of time.
+   *
+   * @throws ConfigurationException if this injector cannot find or create the provider.
+   * @see Binder#getProvider(Key) for an alternative that offers up front error detection
+   */
+  <T> Provider<T> getProvider(Key<T> key);
+
+  /**
+   * Returns the provider used to obtain instances for the given type. When feasible, avoid
+   * using this method, in favor of having Guice inject your dependencies ahead of time.
+   *
+   * @throws ConfigurationException if this injector cannot find or create the provider.
+   * @see Binder#getProvider(Class) for an alternative that offers up front error detection
+   */
+  <T> Provider<T> getProvider(Class<T> type);
+
+  /**
+   * Returns the appropriate instance for the given injection key; equivalent to {@code
+   * getProvider(key).get()}. When feasible, avoid using this method, in favor of having Guice
+   * inject your dependencies ahead of time.
+   *
+   * @throws ConfigurationException if this injector cannot find or create the provider.
+   * @throws ProvisionException if there was a runtime failure while providing an instance.
+   */
+  <T> T getInstance(Key<T> key);
+
+  /**
+   * Returns the appropriate instance for the given injection type; equivalent to {@code
+   * getProvider(type).get()}. When feasible, avoid using this method, in favor of having Guice
+   * inject your dependencies ahead of time.
+   *
+   * @throws ConfigurationException if this injector cannot find or create the provider.
+   * @throws ProvisionException if there was a runtime failure while providing an instance.
+   */
+  <T> T getInstance(Class<T> type);
+
+  /**
+   * Returns this injector's parent, or {@code null} if this is a top-level injector.
+   *
+   * @since 2.0
+   */
+  Injector getParent();
+
+  /**
+   * Returns a new injector that inherits all state from this injector. All bindings, scopes,
+   * interceptors and type converters are inherited -- they are visible to the child injector.
+   * Elements of the child injector are not visible to its parent.
+   *
+   * <p>Just-in-time bindings created for child injectors will be created in an ancestor injector
+   * whenever possible. This allows for scoped instances to be shared between injectors. Use
+   * explicit bindings to prevent bindings from being shared with the parent injector.  Optional
+   * injections in just-in-time bindings (created in the parent injector) may be silently
+   * ignored if the optional dependencies are from the child injector.
+   *
+   * <p>No key may be bound by both an injector and one of its ancestors. This includes just-in-time
+   * bindings. The lone exception is the key for {@code Injector.class}, which is bound by each
+   * injector to itself.
+   *
+   * @since 2.0
+   */
+  Injector createChildInjector(Iterable<? extends Module> modules);
+
+  /**
+   * Returns a new injector that inherits all state from this injector. All bindings, scopes,
+   * interceptors and type converters are inherited -- they are visible to the child injector.
+   * Elements of the child injector are not visible to its parent.
+   *
+   * <p>Just-in-time bindings created for child injectors will be created in an ancestor injector
+   * whenever possible. This allows for scoped instances to be shared between injectors. Use
+   * explicit bindings to prevent bindings from being shared with the parent injector.
+   *
+   * <p>No key may be bound by both an injector and one of its ancestors. This includes just-in-time
+   * bindings. The lone exception is the key for {@code Injector.class}, which is bound by each
+   * injector to itself.
+   *
+   * @since 2.0
+   */
+  Injector createChildInjector(Module... modules);
+
+  /**
+   * Returns a map containing all scopes in the injector. The maps keys are scoping annotations
+   * like {@code Singleton.class}, and the values are scope instances, such as {@code
+   * Scopes.SINGLETON}. The returned map is immutable.
+   *
+   * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+   * 
+   * @since 3.0
+   */
+  Map<Class<? extends Annotation>, Scope> getScopeBindings();
+
+  /**
+   * Returns a set containing all type converter bindings in the injector. The returned set is
+   * immutable.
+   *
+   * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+   * 
+   * @since 3.0
+   */
+  Set<TypeConverterBinding> getTypeConverterBindings();
+}
diff --git a/core/src/com/google/inject/Key.java b/core/src/com/google/inject/Key.java
new file mode 100644
index 0000000..c93dabf
--- /dev/null
+++ b/core/src/com/google/inject/Key.java
@@ -0,0 +1,520 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.inject.internal.Annotations.generateAnnotation;
+import static com.google.inject.internal.Annotations.isAllDefaultMethods;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.inject.internal.Annotations;
+import com.google.inject.internal.MoreTypes;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+/**
+ * Binding key consisting of an injection type and an optional annotation.
+ * Matches the type and annotation at a point of injection.
+ *
+ * <p>For example, {@code Key.get(Service.class, Transactional.class)} will
+ * match:
+ *
+ * <pre>
+ *   {@literal @}Inject
+ *   public void setService({@literal @}Transactional Service service) {
+ *     ...
+ *   }
+ * </pre>
+ *
+ * <p>{@code Key} supports generic types via subclassing just like {@link
+ * TypeLiteral}.
+ *
+ * <p>Keys do not differentiate between primitive types (int, char, etc.) and
+ * their corresponding wrapper types (Integer, Character, etc.). Primitive
+ * types will be replaced with their wrapper types when keys are created.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class Key<T> {
+
+  private final AnnotationStrategy annotationStrategy;
+
+  private final TypeLiteral<T> typeLiteral;
+  private final int hashCode;
+  private final Supplier<String> toStringSupplier;
+
+  /**
+   * Constructs a new key. Derives the type from this class's type parameter.
+   *
+   * <p>Clients create an empty anonymous subclass. Doing so embeds the type
+   * parameter in the anonymous class's type hierarchy so we can reconstitute it
+   * at runtime despite erasure.
+   *
+   * <p>Example usage for a binding of type {@code Foo} annotated with
+   * {@code @Bar}:
+   *
+   * <p>{@code new Key<Foo>(Bar.class) {}}.
+   */
+  @SuppressWarnings("unchecked")
+  protected Key(Class<? extends Annotation> annotationType) {
+    this.annotationStrategy = strategyFor(annotationType);
+    this.typeLiteral = MoreTypes.canonicalizeForKey(
+        (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass()));
+    this.hashCode = computeHashCode();
+    this.toStringSupplier = createToStringSupplier();
+  }
+
+  /**
+   * Constructs a new key. Derives the type from this class's type parameter.
+   *
+   * <p>Clients create an empty anonymous subclass. Doing so embeds the type
+   * parameter in the anonymous class's type hierarchy so we can reconstitute it
+   * at runtime despite erasure.
+   *
+   * <p>Example usage for a binding of type {@code Foo} annotated with
+   * {@code @Bar}:
+   *
+   * <p>{@code new Key<Foo>(new Bar()) {}}.
+   */
+  @SuppressWarnings("unchecked")
+  protected Key(Annotation annotation) {
+    // no usages, not test-covered
+    this.annotationStrategy = strategyFor(annotation);
+    this.typeLiteral = MoreTypes.canonicalizeForKey(
+        (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass()));
+    this.hashCode = computeHashCode();
+    this.toStringSupplier = createToStringSupplier();
+  }
+
+  /**
+   * Constructs a new key. Derives the type from this class's type parameter.
+   *
+   * <p>Clients create an empty anonymous subclass. Doing so embeds the type
+   * parameter in the anonymous class's type hierarchy so we can reconstitute it
+   * at runtime despite erasure.
+   *
+   * <p>Example usage for a binding of type {@code Foo}:
+   *
+   * <p>{@code new Key<Foo>() {}}.
+   */
+  @SuppressWarnings("unchecked")
+  protected Key() {
+    this.annotationStrategy = NullAnnotationStrategy.INSTANCE;
+    this.typeLiteral = MoreTypes.canonicalizeForKey(
+        (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass()));
+    this.hashCode = computeHashCode();
+    this.toStringSupplier = createToStringSupplier();
+  }
+
+  /**
+   * Unsafe. Constructs a key from a manually specified type.
+   */
+  @SuppressWarnings("unchecked")
+  private Key(Type type, AnnotationStrategy annotationStrategy) {
+    this.annotationStrategy = annotationStrategy;
+    this.typeLiteral = MoreTypes.canonicalizeForKey((TypeLiteral<T>) TypeLiteral.get(type));
+    this.hashCode = computeHashCode();
+    this.toStringSupplier = createToStringSupplier();
+  }
+
+  /** Constructs a key from a manually specified type. */
+  private Key(TypeLiteral<T> typeLiteral, AnnotationStrategy annotationStrategy) {
+    this.annotationStrategy = annotationStrategy;
+    this.typeLiteral = MoreTypes.canonicalizeForKey(typeLiteral);
+    this.hashCode = computeHashCode();
+    this.toStringSupplier = createToStringSupplier();
+  }
+
+  /**
+   * Computes the hash code for this key.
+   */
+  private int computeHashCode() {
+    return typeLiteral.hashCode() * 31 + annotationStrategy.hashCode();
+  }
+
+  /**
+   * @return a {@link Supplier} which memoizes the value for lazy initialization.
+   */
+  private Supplier<String> createToStringSupplier() {
+    // The performance hit on access is acceptable since the intended use is for non-performance-
+    // critical applications such as debugging and logging.
+    return Suppliers.memoize(new Supplier<String>() {
+      @Override public String get() {
+        return "Key[type=" + typeLiteral + ", annotation=" + annotationStrategy + "]";
+      }
+    });
+  }
+  
+  /**
+   * Gets the key type.
+   */
+  public final TypeLiteral<T> getTypeLiteral() {
+    return typeLiteral;
+  }
+
+  /**
+   * Gets the annotation type.
+   */
+  public final Class<? extends Annotation> getAnnotationType() {
+    return annotationStrategy.getAnnotationType();
+  }
+
+  /**
+   * Gets the annotation.
+   */
+  public final Annotation getAnnotation() {
+    return annotationStrategy.getAnnotation();
+  }
+
+  boolean hasAnnotationType() {
+    return annotationStrategy.getAnnotationType() != null;
+  }
+
+  String getAnnotationName() {
+    Annotation annotation = annotationStrategy.getAnnotation();
+    if (annotation != null) {
+      return annotation.toString();
+    }
+
+    // not test-covered
+    return annotationStrategy.getAnnotationType().toString();
+  }
+
+  Class<? super T> getRawType() {
+    return typeLiteral.getRawType();
+  }
+
+  /**
+   * Gets the key of this key's provider.
+   */
+  Key<Provider<T>> providerKey() {
+    return ofType(typeLiteral.providerType());
+  }
+
+  @Override public final boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (!(o instanceof Key<?>)) {
+      return false;
+    }
+    Key<?> other = (Key<?>) o;
+    return annotationStrategy.equals(other.annotationStrategy)
+        && typeLiteral.equals(other.typeLiteral);
+  }
+
+  @Override public final int hashCode() {
+    return this.hashCode;
+  }
+
+  @Override public final String toString() {
+    return toStringSupplier.get();
+  }
+
+  /**
+   * Gets a key for an injection type and an annotation strategy.
+   */
+  static <T> Key<T> get(Class<T> type,
+      AnnotationStrategy annotationStrategy) {
+    return new Key<T>(type, annotationStrategy);
+  }
+
+  /**
+   * Gets a key for an injection type.
+   */
+  public static <T> Key<T> get(Class<T> type) {
+    return new Key<T>(type, NullAnnotationStrategy.INSTANCE);
+  }
+
+  /**
+   * Gets a key for an injection type and an annotation type.
+   */
+  public static <T> Key<T> get(Class<T> type,
+      Class<? extends Annotation> annotationType) {
+    return new Key<T>(type, strategyFor(annotationType));
+  }
+
+  /**
+   * Gets a key for an injection type and an annotation.
+   */
+  public static <T> Key<T> get(Class<T> type, Annotation annotation) {
+    return new Key<T>(type, strategyFor(annotation));
+  }
+
+  /**
+   * Gets a key for an injection type.
+   */
+  public static Key<?> get(Type type) {
+    return new Key<Object>(type, NullAnnotationStrategy.INSTANCE);
+  }
+
+  /**
+   * Gets a key for an injection type and an annotation type.
+   */
+  public static Key<?> get(Type type,
+      Class<? extends Annotation> annotationType) {
+    return new Key<Object>(type, strategyFor(annotationType));
+  }
+
+  /**
+   * Gets a key for an injection type and an annotation.
+   */
+  public static Key<?> get(Type type, Annotation annotation) {
+    return new Key<Object>(type, strategyFor(annotation));
+  }
+
+  /**
+   * Gets a key for an injection type.
+   */
+  public static <T> Key<T> get(TypeLiteral<T> typeLiteral) {
+    return new Key<T>(typeLiteral, NullAnnotationStrategy.INSTANCE);
+  }
+
+  /**
+   * Gets a key for an injection type and an annotation type.
+   */
+  public static <T> Key<T> get(TypeLiteral<T> typeLiteral,
+      Class<? extends Annotation> annotationType) {
+    return new Key<T>(typeLiteral, strategyFor(annotationType));
+  }
+
+  /**
+   * Gets a key for an injection type and an annotation.
+   */
+  public static <T> Key<T> get(TypeLiteral<T> typeLiteral,
+      Annotation annotation) {
+    return new Key<T>(typeLiteral, strategyFor(annotation));
+  }
+
+  /**
+   * Returns a new key of the specified type with the same annotation as this
+   * key.
+   *
+   * @since 3.0
+   */
+  public <T> Key<T> ofType(Class<T> type) {
+    return new Key<T>(type, annotationStrategy);
+  }
+
+  /**
+   * Returns a new key of the specified type with the same annotation as this
+   * key.
+   *
+   * @since 3.0
+   */
+  public Key<?> ofType(Type type) {
+    return new Key<Object>(type, annotationStrategy);
+  }
+
+  /**
+   * Returns a new key of the specified type with the same annotation as this
+   * key.
+   *
+   * @since 3.0
+   */
+  public <T> Key<T> ofType(TypeLiteral<T> type) {
+    return new Key<T>(type, annotationStrategy);
+  }
+
+  /**
+   * Returns true if this key has annotation attributes.
+   *
+   * @since 3.0
+   */
+  public boolean hasAttributes() {
+    return annotationStrategy.hasAttributes();
+  }
+
+  /**
+   * Returns this key without annotation attributes, i.e. with only the
+   * annotation type.
+   *
+   * @since 3.0
+   */
+  public Key<T> withoutAttributes() {
+    return new Key<T>(typeLiteral, annotationStrategy.withoutAttributes());
+  }
+
+  interface AnnotationStrategy {
+    Annotation getAnnotation();
+    Class<? extends Annotation> getAnnotationType();
+    boolean hasAttributes();
+    AnnotationStrategy withoutAttributes();
+  }
+
+  /**
+   * Gets the strategy for an annotation.
+   */
+  static AnnotationStrategy strategyFor(Annotation annotation) {
+    checkNotNull(annotation, "annotation");
+    Class<? extends Annotation> annotationType = annotation.annotationType();
+    ensureRetainedAtRuntime(annotationType);
+    ensureIsBindingAnnotation(annotationType);
+
+    if (Annotations.isMarker(annotationType)) {
+      return new AnnotationTypeStrategy(annotationType, annotation);
+    }
+
+    return new AnnotationInstanceStrategy(Annotations.canonicalizeIfNamed(annotation));
+  }
+
+  /**
+   * Gets the strategy for an annotation type.
+   */
+  static AnnotationStrategy strategyFor(Class<? extends Annotation> annotationType) {
+    annotationType = Annotations.canonicalizeIfNamed(annotationType);
+    if (isAllDefaultMethods(annotationType)) {
+      return strategyFor(generateAnnotation(annotationType));
+    }
+
+    checkNotNull(annotationType, "annotation type");
+    ensureRetainedAtRuntime(annotationType);
+    ensureIsBindingAnnotation(annotationType);
+    return new AnnotationTypeStrategy(annotationType, null);
+
+  }
+
+  private static void ensureRetainedAtRuntime(
+      Class<? extends Annotation> annotationType) {
+    checkArgument(Annotations.isRetainedAtRuntime(annotationType),
+        "%s is not retained at runtime. Please annotate it with @Retention(RUNTIME).",
+        annotationType.getName());
+  }
+
+  private static void ensureIsBindingAnnotation(Class<? extends Annotation> annotationType) {
+    checkArgument(Annotations.isBindingAnnotation(annotationType),
+        "%s is not a binding annotation. Please annotate it with @BindingAnnotation.",
+        annotationType.getName());
+  }
+
+  static enum NullAnnotationStrategy implements AnnotationStrategy {
+    INSTANCE;
+
+    public boolean hasAttributes() {
+      return false;
+    }
+
+    public AnnotationStrategy withoutAttributes() {
+      throw new UnsupportedOperationException("Key already has no attributes.");
+    }
+
+    public Annotation getAnnotation() {
+      return null;
+    }
+
+    public Class<? extends Annotation> getAnnotationType() {
+      return null;
+    }
+
+    @Override public String toString() {
+      return "[none]";
+    }
+  }
+
+  // this class not test-covered
+  static class AnnotationInstanceStrategy implements AnnotationStrategy {
+
+    final Annotation annotation;
+
+    AnnotationInstanceStrategy(Annotation annotation) {
+      this.annotation = checkNotNull(annotation, "annotation");
+    }
+
+    public boolean hasAttributes() {
+      return true;
+    }
+
+    public AnnotationStrategy withoutAttributes() {
+      return new AnnotationTypeStrategy(getAnnotationType(), annotation);
+    }
+
+    public Annotation getAnnotation() {
+      return annotation;
+    }
+
+    public Class<? extends Annotation> getAnnotationType() {
+      return annotation.annotationType();
+    }
+
+    @Override public boolean equals(Object o) {
+      if (!(o instanceof AnnotationInstanceStrategy)) {
+        return false;
+      }
+
+      AnnotationInstanceStrategy other = (AnnotationInstanceStrategy) o;
+      return annotation.equals(other.annotation);
+    }
+
+    @Override public int hashCode() {
+      return annotation.hashCode();
+    }
+
+    @Override public String toString() {
+      return annotation.toString();
+    }
+  }
+
+  static class AnnotationTypeStrategy implements AnnotationStrategy {
+
+    final Class<? extends Annotation> annotationType;
+
+    // Keep the instance around if we have it so the client can request it.
+    final Annotation annotation;
+
+    AnnotationTypeStrategy(Class<? extends Annotation> annotationType,
+        Annotation annotation) {
+      this.annotationType = checkNotNull(annotationType, "annotation type");
+      this.annotation = annotation;
+    }
+
+    public boolean hasAttributes() {
+      return false;
+    }
+
+    public AnnotationStrategy withoutAttributes() {
+      throw new UnsupportedOperationException("Key already has no attributes.");
+    }
+
+    public Annotation getAnnotation() {
+      return annotation;
+    }
+
+    public Class<? extends Annotation> getAnnotationType() {
+      return annotationType;
+    }
+
+    @Override public boolean equals(Object o) {
+      if (!(o instanceof AnnotationTypeStrategy)) {
+        return false;
+      }
+
+      AnnotationTypeStrategy other = (AnnotationTypeStrategy) o;
+      return annotationType.equals(other.annotationType);
+    }
+
+    @Override public int hashCode() {
+      return annotationType.hashCode();
+    }
+
+    @Override public String toString() {
+      return "@" + annotationType.getName();
+    }
+  }
+}
diff --git a/core/src/com/google/inject/MembersInjector.java b/core/src/com/google/inject/MembersInjector.java
new file mode 100644
index 0000000..b50dedb
--- /dev/null
+++ b/core/src/com/google/inject/MembersInjector.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.google.inject;
+
+/**
+ * Injects dependencies into the fields and methods on instances of type {@code T}. Ignores the
+ * presence or absence of an injectable constructor.
+ *
+ * @param <T> type to inject members of
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface MembersInjector<T> {
+
+  /**
+   * Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
+   * absence of an injectable constructor.
+   *
+   * <p>Whenever Guice creates an instance, it performs this injection automatically (after first
+   * performing constructor injection), so if you're able to let Guice create all your objects for
+   * you, you'll never need to use this method.
+   *
+   * @param instance to inject members on. May be {@code null}.
+   */
+  void injectMembers(T instance);
+}
diff --git a/core/src/com/google/inject/Module.java b/core/src/com/google/inject/Module.java
new file mode 100644
index 0000000..f22d93f
--- /dev/null
+++ b/core/src/com/google/inject/Module.java
@@ -0,0 +1,43 @@
+/**
+ * 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 com.google.inject;
+
+/**
+ * A module contributes configuration information, typically interface
+ * bindings, which will be used to create an {@link Injector}. A Guice-based
+ * application is ultimately composed of little more than a set of
+ * {@code Module}s and some bootstrapping code.
+ *
+ * <p>Your Module classes can use a more streamlined syntax by extending
+ * {@link AbstractModule} rather than implementing this interface directly.
+ *
+ * <p>In addition to the bindings configured via {@link #configure}, bindings
+ * will be created for all methods annotated with {@literal @}{@link Provides}.
+ * Use scope and binding annotations on these methods to configure the
+ * bindings.
+ */
+public interface Module {
+
+  /**
+   * Contributes bindings and other configurations for this module to {@code binder}.
+   *
+   * <p><strong>Do not invoke this method directly</strong> to install submodules. Instead use
+   * {@link Binder#install(Module)}, which ensures that {@link Provides provider methods} are
+   * discovered.
+   */
+  void configure(Binder binder);
+}
diff --git a/core/src/com/google/inject/OutOfScopeException.java b/core/src/com/google/inject/OutOfScopeException.java
new file mode 100644
index 0000000..430fa23
--- /dev/null
+++ b/core/src/com/google/inject/OutOfScopeException.java
@@ -0,0 +1,39 @@
+/**
+ * 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 com.google.inject;
+
+/**
+ * Thrown from {@link Provider#get} when an attempt is made to access a scoped
+ * object while the scope in question is not currently active.
+ *
+ * @author kevinb@google.com (Kevin Bourrillion)
+ * @since 2.0
+ */
+public final class OutOfScopeException extends RuntimeException {
+
+  public OutOfScopeException(String message) {
+    super(message);
+  }
+
+  public OutOfScopeException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public OutOfScopeException(Throwable cause) {
+    super(cause);
+  }
+}
diff --git a/core/src/com/google/inject/PrivateBinder.java b/core/src/com/google/inject/PrivateBinder.java
new file mode 100644
index 0000000..21a833f
--- /dev/null
+++ b/core/src/com/google/inject/PrivateBinder.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 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.inject;
+
+import com.google.inject.binder.AnnotatedElementBuilder;
+
+/**
+ * Returns a binder whose configuration information is hidden from its environment by default. See
+ * {@link com.google.inject.PrivateModule PrivateModule} for details.
+ * 
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface PrivateBinder extends Binder {
+
+  /** Makes the binding for {@code key} available to the enclosing environment */
+  void expose(Key<?> key);
+
+  /**
+   * Makes a binding for {@code type} available to the enclosing environment. Use {@link
+   * com.google.inject.binder.AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+   * binding annotation.
+   */
+  AnnotatedElementBuilder expose(Class<?> type);
+
+  /**
+   * Makes a binding for {@code type} available to the enclosing environment. Use {@link
+   * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+   * binding annotation.
+   */
+  AnnotatedElementBuilder expose(TypeLiteral<?> type);
+
+  PrivateBinder withSource(Object source);
+
+  PrivateBinder skipSources(Class... classesToSkip);
+}
diff --git a/core/src/com/google/inject/PrivateModule.java b/core/src/com/google/inject/PrivateModule.java
new file mode 100644
index 0000000..ba2f722
--- /dev/null
+++ b/core/src/com/google/inject/PrivateModule.java
@@ -0,0 +1,306 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.AnnotatedConstantBindingBuilder;
+import com.google.inject.binder.AnnotatedElementBuilder;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.ProvisionListener;
+import com.google.inject.spi.TypeConverter;
+import com.google.inject.spi.TypeListener;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * A module whose configuration information is hidden from its environment by default. Only bindings
+ * that are explicitly exposed will be available to other modules and to the users of the injector.
+ * This module may expose the bindings it creates and the bindings of the modules it installs.
+ *
+ * <p>A private module can be nested within a regular module or within another private module using
+ * {@link Binder#install install()}.  Its bindings live in a new environment that inherits bindings,
+ * type converters, scopes, and interceptors from the surrounding ("parent") environment.  When you
+ * nest multiple private modules, the result is a tree of environments where the injector's
+ * environment is the root.
+ *
+ * <p>Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link
+ * com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link
+ * Exposed} annotation:
+ *
+ * <pre>
+ * public class FooBarBazModule extends PrivateModule {
+ *   protected void configure() {
+ *     bind(Foo.class).to(RealFoo.class);
+ *     expose(Foo.class);
+ *
+ *     install(new TransactionalBarModule());
+ *     expose(Bar.class).annotatedWith(Transactional.class);
+ *
+ *     bind(SomeImplementationDetail.class);
+ *     install(new MoreImplementationDetailsModule());
+ *   }
+ *
+ *   {@literal @}Provides {@literal @}Exposed
+ *   public Baz provideBaz() {
+ *     return new SuperBaz();
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent
+ * injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the
+ * root environment. Such bindings are shared among all environments in the tree.
+ * 
+ * <p>The scope of a binding is constrained to its environment. A singleton bound in a private
+ * module will be unique to its environment. But a binding for the same type in a different private
+ * module will yield a different instance.
+ *
+ * <p>A shared binding that injects the {@code Injector} gets the root injector, which only has
+ * access to bindings in the root environment. An explicit binding that injects the {@code Injector}
+ * gets access to all bindings in the child environment.
+ *
+ * <p>To promote a just-in-time binding to an explicit binding, bind it:
+ * <pre>
+ *   bind(FooImpl.class);
+ * </pre>
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public abstract class PrivateModule implements Module {
+
+  /** Like abstract module, the binder of the current private module */
+  private PrivateBinder binder;
+
+  public final synchronized void configure(Binder binder) {
+    checkState(this.binder == null, "Re-entry is not allowed.");
+
+    // Guice treats PrivateModules specially and passes in a PrivateBinder automatically.
+    this.binder = (PrivateBinder) binder.skipSources(PrivateModule.class);
+    try {
+      configure();
+    } finally {
+      this.binder = null;
+    }
+  }
+
+  /**
+   * Creates bindings and other configurations private to this module. Use {@link #expose(Class)
+   * expose()} to make the bindings in this module available externally.
+   */
+  protected abstract void configure();
+
+  /** Makes the binding for {@code key} available to other modules and the injector. */
+  protected final <T> void expose(Key<T> key) {
+    binder().expose(key);
+  }
+
+  /**
+   * Makes a binding for {@code type} available to other modules and the injector. Use {@link
+   * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+   * binding annotation.
+   */
+  protected final AnnotatedElementBuilder expose(Class<?> type) {
+    return binder().expose(type);
+  }
+
+  /**
+   * Makes a binding for {@code type} available to other modules and the injector. Use {@link
+   * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+   * binding annotation.
+   */
+  protected final AnnotatedElementBuilder expose(TypeLiteral<?> type) {
+    return binder().expose(type);
+  }
+
+  // everything below is copied from AbstractModule
+
+  /**
+   * Returns the current binder.
+   */
+  protected final PrivateBinder binder() {
+    checkState(binder != null, "The binder can only be used inside configure()");
+    return binder;
+  }
+
+  /**
+   * @see Binder#bindScope(Class, Scope)
+   */
+  protected final void bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope) {
+    binder().bindScope(scopeAnnotation, scope);
+  }
+
+  /**
+   * @see Binder#bind(Key)
+   */
+  protected final <T> LinkedBindingBuilder<T> bind(Key<T> key) {
+    return binder().bind(key);
+  }
+
+  /**
+   * @see Binder#bind(TypeLiteral)
+   */
+  protected final <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
+    return binder().bind(typeLiteral);
+  }
+
+  /**
+   * @see Binder#bind(Class)  
+   */
+  protected final <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) {
+    return binder().bind(clazz);
+  }
+
+  /**
+   * @see Binder#bindConstant()
+   */
+  protected final AnnotatedConstantBindingBuilder bindConstant() {
+    return binder().bindConstant();
+  }
+
+  /**
+   * @see Binder#install(Module)
+   */
+  protected final void install(Module module) {
+    binder().install(module);
+  }
+
+  /**
+   * @see Binder#addError(String, Object[])
+   */
+  protected final void addError(String message, Object... arguments) {
+    binder().addError(message, arguments);
+  }
+
+  /**
+   * @see Binder#addError(Throwable)
+   */
+  protected final void addError(Throwable t) {
+    binder().addError(t);
+  }
+
+  /**
+   * @see Binder#addError(Message)
+   */
+  protected final void addError(Message message) {
+    binder().addError(message);
+  }
+
+  /**
+   * @see Binder#requestInjection(Object)
+   */
+  protected final void requestInjection(Object instance) {
+    binder().requestInjection(instance);
+  }
+
+  /**
+   * @see Binder#requestStaticInjection(Class[])
+   */
+  protected final void requestStaticInjection(Class<?>... types) {
+    binder().requestStaticInjection(types);
+  }
+
+  /*if[AOP]*/
+  /**
+   * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])
+   */
+  protected final void bindInterceptor(Matcher<? super Class<?>> classMatcher,
+      Matcher<? super Method> methodMatcher,
+      org.aopalliance.intercept.MethodInterceptor... interceptors) {
+    binder().bindInterceptor(classMatcher, methodMatcher, interceptors);
+  }
+  /*end[AOP]*/
+
+  /**
+   * Instructs Guice to require a binding to the given key.
+   */
+  protected final void requireBinding(Key<?> key) {
+    binder().getProvider(key);
+  }
+
+  /**
+   * Instructs Guice to require a binding to the given type.
+   */
+  protected final void requireBinding(Class<?> type) {
+    binder().getProvider(type);
+  }
+
+  /**
+   * @see Binder#getProvider(Key)
+   */
+  protected final <T> Provider<T> getProvider(Key<T> key) {
+    return binder().getProvider(key);
+  }
+  
+  /**
+   * @see Binder#getProvider(Class)
+   */
+  protected final <T> Provider<T> getProvider(Class<T> type) {
+    return binder().getProvider(type);
+  }
+
+  /**
+   * @see Binder#convertToTypes(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeConverter)
+   */
+  protected final void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
+      TypeConverter converter) {
+    binder().convertToTypes(typeMatcher, converter);
+  }
+
+  /**
+   * @see Binder#currentStage()
+   */
+  protected final Stage currentStage() {
+    return binder().currentStage();
+  }
+
+  /**
+   * @see Binder#getMembersInjector(Class)
+   */
+  protected <T> MembersInjector<T> getMembersInjector(Class<T> type) {
+    return binder().getMembersInjector(type);
+  }
+
+  /**
+   * @see Binder#getMembersInjector(TypeLiteral)
+   */
+  protected <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> type) {
+    return binder().getMembersInjector(type);
+  }
+
+  /**
+   * @see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener)
+   */
+  protected void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher,
+      TypeListener listener) {
+    binder().bindListener(typeMatcher, listener);
+  }
+  
+  /**
+   * @see Binder#bindListener(Matcher, ProvisionListener...)
+   * @since 4.0
+   */
+  protected void bindListener(Matcher<? super Binding<?>> bindingMatcher,
+      ProvisionListener... listeners) {
+    binder().bindListener(bindingMatcher, listeners);
+  }
+}
diff --git a/core/src/com/google/inject/ProvidedBy.java b/core/src/com/google/inject/ProvidedBy.java
new file mode 100644
index 0000000..7ad12f7
--- /dev/null
+++ b/core/src/com/google/inject/ProvidedBy.java
@@ -0,0 +1,38 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * A pointer to the default provider type for a type.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Retention(RUNTIME)
+@Target(TYPE)
+public @interface ProvidedBy {
+
+  /**
+   * The implementation type.
+   */
+  Class<? extends Provider<?>> value();
+}
diff --git a/core/src/com/google/inject/Provider.java b/core/src/com/google/inject/Provider.java
new file mode 100644
index 0000000..3295a2b
--- /dev/null
+++ b/core/src/com/google/inject/Provider.java
@@ -0,0 +1,56 @@
+/**
+ * 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 com.google.inject;
+
+/**
+ * An object capable of providing instances of type {@code T}. Providers are used in numerous ways
+ * by Guice:
+ *
+ * <ul>
+ * <li>When the default means for obtaining instances (an injectable or parameterless constructor)
+ * is insufficient for a particular binding, the module can specify a custom {@code Provider}
+ * instead, to control exactly how Guice creates or obtains instances for the binding.
+ *
+ * <li>An implementation class may always choose to have a {@code Provider<T>} instance injected,
+ * rather than having a {@code T} injected directly.  This may give you access to multiple
+ * instances, instances you wish to safely mutate and discard, instances which are out of scope
+ * (e.g. using a {@code @RequestScoped} object from within a {@code @SessionScoped} object), or
+ * instances that will be initialized lazily.
+ *
+ * <li>A custom {@link Scope} is implemented as a decorator of {@code Provider<T>}, which decides
+ * when to delegate to the backing provider and when to provide the instance some other way.
+ *
+ * <li>The {@link Injector} offers access to the {@code Provider<T>} it uses to fulfill requests
+ * for a given key, via the {@link Injector#getProvider} methods.
+ * </ul>
+ *
+ * @param <T> the type of object this provides
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public interface Provider<T> extends javax.inject.Provider<T> {
+
+  /**
+   * Provides an instance of {@code T}. Must never return {@code null}.
+   *
+   * @throws OutOfScopeException when an attempt is made to access a scoped object while the scope
+   *     in question is not currently active
+   * @throws ProvisionException if an instance cannot be provided. Such exceptions include messages
+   *     and throwables to describe why provision failed.
+   */
+  T get();
+}
diff --git a/core/src/com/google/inject/Provides.java b/core/src/com/google/inject/Provides.java
new file mode 100644
index 0000000..c66a428
--- /dev/null
+++ b/core/src/com/google/inject/Provides.java
@@ -0,0 +1,34 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates methods of a {@link Module} to create a provider method binding. The method's return
+ * type is bound to its returned value. Guice will pass dependencies to the method as parameters.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @since 2.0
+ */
+@Documented @Target(METHOD) @Retention(RUNTIME)
+public @interface Provides {}
diff --git a/core/src/com/google/inject/ProvisionException.java b/core/src/com/google/inject/ProvisionException.java
new file mode 100644
index 0000000..3c590b9
--- /dev/null
+++ b/core/src/com/google/inject/ProvisionException.java
@@ -0,0 +1,64 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.internal.Errors;
+import com.google.inject.spi.Message;
+
+import java.util.Collection;
+
+/**
+ * Indicates that there was a runtime failure while providing an instance.
+ *
+ * @author kevinb@google.com (Kevin Bourrillion)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class ProvisionException extends RuntimeException {
+
+  private final ImmutableSet<Message> messages;
+
+  /** Creates a ProvisionException containing {@code messages}. */
+  public ProvisionException(Iterable<Message> messages) {
+    this.messages = ImmutableSet.copyOf(messages);
+    checkArgument(!this.messages.isEmpty());
+    initCause(Errors.getOnlyCause(this.messages));
+  }
+
+  public ProvisionException(String message, Throwable cause) {
+    super(cause);
+    this.messages = ImmutableSet.of(new Message(message, cause));
+  }
+
+  public ProvisionException(String message) {
+    this.messages = ImmutableSet.of(new Message(message));
+  }
+
+  /** Returns messages for the errors that caused this exception. */
+  public Collection<Message> getErrorMessages() {
+    return messages;
+  }
+
+  @Override public String getMessage() {
+    return Errors.format("Unable to provision, see the following errors", messages);
+  }
+
+  private static final long serialVersionUID = 0;
+}
diff --git a/core/src/com/google/inject/Scope.java b/core/src/com/google/inject/Scope.java
new file mode 100644
index 0000000..949270c
--- /dev/null
+++ b/core/src/com/google/inject/Scope.java
@@ -0,0 +1,59 @@
+/**
+ * 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 com.google.inject;
+
+/**
+ * A scope is a level of visibility that instances provided by Guice may have.
+ * By default, an instance created by the {@link Injector} has <i>no scope</i>,
+ * meaning it has no state from the framework's perspective -- the
+ * {@code Injector} creates it, injects it once into the class that required it,
+ * and then immediately forgets it. Associating a scope with a particular
+ * binding allows the created instance to be "remembered" and possibly used
+ * again for other injections.
+ *
+ * <p>An example of a scope is {@link Scopes#SINGLETON}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public interface Scope {
+
+  /**
+   * Scopes a provider. The returned provider returns objects from this scope.
+   * If an object does not exist in this scope, the provider can use the given
+   * unscoped provider to retrieve one.
+   *
+   * <p>Scope implementations are strongly encouraged to override
+   * {@link Object#toString} in the returned provider and include the backing
+   * provider's {@code toString()} output.
+   *
+   * @param key binding key
+   * @param unscoped locates an instance when one doesn't already exist in this
+   *  scope.
+   * @return a new provider which only delegates to the given unscoped provider
+   *  when an instance of the requested object doesn't already exist in this
+   *  scope
+   */
+  public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped);
+
+  /**
+   * A short but useful description of this scope.  For comparison, the standard
+   * scopes that ship with guice use the descriptions
+   * {@code "Scopes.SINGLETON"}, {@code "ServletScopes.SESSION"} and
+   * {@code "ServletScopes.REQUEST"}.
+   */
+  String toString();
+}
diff --git a/core/src/com/google/inject/ScopeAnnotation.java b/core/src/com/google/inject/ScopeAnnotation.java
new file mode 100644
index 0000000..8f869a0
--- /dev/null
+++ b/core/src/com/google/inject/ScopeAnnotation.java
@@ -0,0 +1,41 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates annotations which are used for scoping. Only one such annotation
+ * may apply to a single implementation class. You must also annotate scope
+ * annotations with {@code @Retention(RUNTIME)}. For example:
+ *
+ * <pre>
+ *   {@code @}Retention(RUNTIME)
+ *   {@code @}Target(TYPE, METHOD)
+ *   {@code @}ScopeAnnotation
+ *   public {@code @}interface SessionScoped {}
+ * </pre>
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Target(ANNOTATION_TYPE)
+@Retention(RUNTIME)
+public @interface ScopeAnnotation {}
diff --git a/core/src/com/google/inject/Scopes.java b/core/src/com/google/inject/Scopes.java
new file mode 100644
index 0000000..6c893e5
--- /dev/null
+++ b/core/src/com/google/inject/Scopes.java
@@ -0,0 +1,187 @@
+/**
+ * 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 com.google.inject;
+
+import com.google.inject.internal.CircularDependencyProxy;
+import com.google.inject.internal.LinkedBindingImpl;
+import com.google.inject.internal.SingletonScope;
+import com.google.inject.spi.BindingScopingVisitor;
+import com.google.inject.spi.ExposedBinding;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Built-in scope implementations.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class Scopes {
+
+  private Scopes() {}
+
+  /**
+   * One instance per {@link Injector}. Also see {@code @}{@link Singleton}.
+   */
+  public static final Scope SINGLETON = new SingletonScope();
+
+  /**
+   * No scope; the same as not applying any scope at all.  Each time the
+   * Injector obtains an instance of an object with "no scope", it injects this
+   * instance then immediately forgets it.  When the next request for the same
+   * binding arrives it will need to obtain the instance over again.
+   *
+   * <p>This exists only in case a class has been annotated with a scope
+   * annotation such as {@link Singleton @Singleton}, and you need to override
+   * this to "no scope" in your binding.
+   *
+   * @since 2.0
+   */
+  public static final Scope NO_SCOPE = new Scope() {
+    public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
+      return unscoped;
+    }
+    @Override public String toString() {
+      return "Scopes.NO_SCOPE";
+    }
+  };
+
+  private static final BindingScopingVisitor<Boolean> IS_SINGLETON_VISITOR
+      = new BindingScopingVisitor<Boolean>() {
+        public Boolean visitNoScoping() {
+          return false;
+        }
+
+        public Boolean visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
+          return scopeAnnotation == Singleton.class
+              || scopeAnnotation == javax.inject.Singleton.class;
+        }
+
+        public Boolean visitScope(Scope scope) {
+          return scope == Scopes.SINGLETON;
+        }
+
+        public Boolean visitEagerSingleton() {
+          return true;
+        }
+      };
+
+  /**
+   * Returns true if {@code binding} is singleton-scoped. If the binding is a {@link
+   * com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it
+   * was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will
+   * also true if the target binding is singleton-scoped.
+   *
+   * @since 3.0
+   */
+  public static boolean isSingleton(Binding<?> binding) {
+    do {
+      boolean singleton = binding.acceptScopingVisitor(IS_SINGLETON_VISITOR);
+      if (singleton) {
+        return true;
+      }
+
+      if (binding instanceof LinkedBindingImpl) {
+        LinkedBindingImpl<?> linkedBinding = (LinkedBindingImpl) binding;
+        Injector injector = linkedBinding.getInjector();
+        if (injector != null) {
+          binding = injector.getBinding(linkedBinding.getLinkedKey());
+          continue;
+        }
+      } else if(binding instanceof ExposedBinding) {
+        ExposedBinding<?> exposedBinding = (ExposedBinding)binding;
+        Injector injector = exposedBinding.getPrivateElements().getInjector();
+        if (injector != null) {
+          binding = injector.getBinding(exposedBinding.getKey());
+          continue;
+        }
+      }
+
+      return false;
+    } while (true);
+  }
+
+  /**
+
+   * Returns true if {@code binding} has the given scope. If the binding is a {@link
+   * com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it
+   * was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will
+   * also true if the target binding has the given scope.
+   *
+   * @param binding binding to check
+   * @param scope scope implementation instance
+   * @param scopeAnnotation scope annotation class
+   * @since 4.0
+   */
+  public static boolean isScoped(Binding<?> binding, final Scope scope,
+      final Class<? extends Annotation> scopeAnnotation) {
+    do {
+      boolean matches = binding.acceptScopingVisitor(new BindingScopingVisitor<Boolean>() {
+        public Boolean visitNoScoping() {
+          return false;
+        }
+
+        public Boolean visitScopeAnnotation(Class<? extends Annotation> visitedAnnotation) {
+          return visitedAnnotation == scopeAnnotation;
+        }
+
+        public Boolean visitScope(Scope visitedScope) {
+          return visitedScope == scope;
+        }
+
+        public Boolean visitEagerSingleton() {
+          return false;
+        }
+      });
+
+      if (matches) {
+        return true;
+      }
+
+      if (binding instanceof LinkedBindingImpl) {
+        LinkedBindingImpl<?> linkedBinding = (LinkedBindingImpl) binding;
+        Injector injector = linkedBinding.getInjector();
+        if (injector != null) {
+          binding = injector.getBinding(linkedBinding.getLinkedKey());
+          continue;
+        }
+      } else if(binding instanceof ExposedBinding) {
+        ExposedBinding<?> exposedBinding = (ExposedBinding)binding;
+        Injector injector = exposedBinding.getPrivateElements().getInjector();
+        if (injector != null) {
+          binding = injector.getBinding(exposedBinding.getKey());
+          continue;
+        }
+      }
+
+      return false;
+    } while (true);
+  }
+
+  /**
+   * Returns true if the object is a proxy for a circular dependency,
+   * constructed by Guice because it encountered a circular dependency. Scope
+   * implementations should be careful to <b>not cache circular proxies</b>,
+   * because the proxies are not intended for general purpose use. (They are
+   * designed just to fulfill the immediate injection, not all injections.
+   * Caching them can lead to IllegalArgumentExceptions or ClassCastExceptions.)
+   *
+   * @since 4.0
+   */
+  public static boolean isCircularProxy(Object object) {
+    return object instanceof CircularDependencyProxy;
+  }
+}
diff --git a/core/src/com/google/inject/Singleton.java b/core/src/com/google/inject/Singleton.java
new file mode 100644
index 0000000..0ea9a14
--- /dev/null
+++ b/core/src/com/google/inject/Singleton.java
@@ -0,0 +1,34 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Apply this to implementation classes when you want only one instance
+ * (per {@link Injector}) to be reused for all injections for that binding.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RUNTIME)
+@ScopeAnnotation
+public @interface Singleton {}
diff --git a/core/src/com/google/inject/Stage.java b/core/src/com/google/inject/Stage.java
new file mode 100644
index 0000000..f9b4e35
--- /dev/null
+++ b/core/src/com/google/inject/Stage.java
@@ -0,0 +1,44 @@
+/**
+ * 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 com.google.inject;
+
+/**
+ * The stage we're running in.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public enum Stage {
+
+  /**
+   * We're running in a tool (an IDE plugin for example). We need binding meta data but not a
+   * functioning Injector. Do not inject members of instances. Do not load eager singletons. Do as
+   * little as possible so our tools run nice and snappy. Injectors created in this stage cannot
+   * be used to satisfy injections.
+   */
+  TOOL,
+
+  /**
+   * We want fast startup times at the expense of runtime performance and some up front error
+   * checking.
+   */
+  DEVELOPMENT,
+
+  /**
+   * We want to catch errors as early as possible and take performance hits up front.
+   */
+  PRODUCTION
+}
diff --git a/core/src/com/google/inject/TypeLiteral.java b/core/src/com/google/inject/TypeLiteral.java
new file mode 100644
index 0000000..d18087d
--- /dev/null
+++ b/core/src/com/google/inject/TypeLiteral.java
@@ -0,0 +1,341 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.inject.internal.MoreTypes.canonicalize;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.internal.MoreTypes;
+import com.google.inject.util.Types;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.List;
+
+/**
+ * Represents a generic type {@code T}. Java doesn't yet provide a way to
+ * represent generic types, so this class does. Forces clients to create a
+ * subclass of this class which enables retrieval the type information even at
+ * runtime.
+ *
+ * <p>For example, to create a type literal for {@code List<String>}, you can
+ * create an empty anonymous inner class:
+ *
+ * <p>
+ * {@code TypeLiteral<List<String>> list = new TypeLiteral<List<String>>() {};}
+ *
+ * <p>Along with modeling generic types, this class can resolve type parameters.
+ * For example, to figure out what type {@code keySet()} returns on a {@code
+ * Map<Integer, String>}, use this code:<pre>   {@code
+ *
+ *   TypeLiteral<Map<Integer, String>> mapType
+ *       = new TypeLiteral<Map<Integer, String>>() {};
+ *   TypeLiteral<?> keySetType
+ *       = mapType.getReturnType(Map.class.getMethod("keySet"));
+ *   System.out.println(keySetType); // prints "Set<Integer>"}</pre>
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class TypeLiteral<T> {
+
+  final Class<? super T> rawType;
+  final Type type;
+  final int hashCode;
+
+  /**
+   * Constructs a new type literal. Derives represented class from type
+   * parameter.
+   *
+   * <p>Clients create an empty anonymous subclass. Doing so embeds the type
+   * parameter in the anonymous class's type hierarchy so we can reconstitute it
+   * at runtime despite erasure.
+   */
+  @SuppressWarnings("unchecked")
+  protected TypeLiteral() {
+    this.type = getSuperclassTypeParameter(getClass());
+    this.rawType = (Class<? super T>) MoreTypes.getRawType(type);
+    this.hashCode = type.hashCode();
+  }
+
+  /**
+   * Unsafe. Constructs a type literal manually.
+   */
+  @SuppressWarnings("unchecked")
+  TypeLiteral(Type type) {
+    this.type = canonicalize(checkNotNull(type, "type"));
+    this.rawType = (Class<? super T>) MoreTypes.getRawType(this.type);
+    this.hashCode = this.type.hashCode();
+  }
+
+  /**
+   * Returns the type from super class's type parameter in {@link MoreTypes#canonicalize(Type)
+   * canonical form}.
+   */
+  static Type getSuperclassTypeParameter(Class<?> subclass) {
+    Type superclass = subclass.getGenericSuperclass();
+    if (superclass instanceof Class) {
+      throw new RuntimeException("Missing type parameter.");
+    }
+    ParameterizedType parameterized = (ParameterizedType) superclass;
+    return canonicalize(parameterized.getActualTypeArguments()[0]);
+  }
+
+  /**
+   * Gets type literal from super class's type parameter.
+   */
+  static TypeLiteral<?> fromSuperclassTypeParameter(Class<?> subclass) {
+    return new TypeLiteral<Object>(getSuperclassTypeParameter(subclass));
+  }
+
+  /**
+   * Returns the raw (non-generic) type for this type.
+   * 
+   * @since 2.0
+   */
+  public final Class<? super T> getRawType() {
+    return rawType;
+  }
+
+  /**
+   * Gets underlying {@code Type} instance.
+   */
+  public final Type getType() {
+    return type;
+  }
+
+  /**
+   * Gets the type of this type's provider.
+   */
+  @SuppressWarnings("unchecked")
+  final TypeLiteral<Provider<T>> providerType() {
+    // This cast is safe and wouldn't generate a warning if Type had a type
+    // parameter.
+    return (TypeLiteral<Provider<T>>) get(Types.providerOf(getType()));
+  }
+
+  @Override public final int hashCode() {
+    return this.hashCode;
+  }
+
+  @Override public final boolean equals(Object o) {
+    return o instanceof TypeLiteral<?>
+        && MoreTypes.equals(type, ((TypeLiteral) o).type);
+  }
+
+  @Override public final String toString() {
+    return MoreTypes.typeToString(type);
+  }
+
+  /**
+   * Gets type literal for the given {@code Type} instance.
+   */
+  public static TypeLiteral<?> get(Type type) {
+    return new TypeLiteral<Object>(type);
+  }
+
+  /**
+   * Gets type literal for the given {@code Class} instance.
+   */
+  public static <T> TypeLiteral<T> get(Class<T> type) {
+    return new TypeLiteral<T>(type);
+  }
+
+
+  /** Returns an immutable list of the resolved types. */
+  private List<TypeLiteral<?>> resolveAll(Type[] types) {
+    TypeLiteral<?>[] result = new TypeLiteral<?>[types.length];
+    for (int t = 0; t < types.length; t++) {
+      result[t] = resolve(types[t]);
+    }
+    return ImmutableList.copyOf(result);
+  }
+
+  /**
+   * Resolves known type parameters in {@code toResolve} and returns the result.
+   */
+  TypeLiteral<?> resolve(Type toResolve) {
+    return TypeLiteral.get(resolveType(toResolve));
+  }
+
+  Type resolveType(Type toResolve) {
+    // this implementation is made a little more complicated in an attempt to avoid object-creation
+    while (true) {
+      if (toResolve instanceof TypeVariable) {
+        TypeVariable original = (TypeVariable) toResolve;
+        toResolve = MoreTypes.resolveTypeVariable(type, rawType, original);
+        if (toResolve == original) {
+          return toResolve;
+        }
+
+      } else if (toResolve instanceof GenericArrayType) {
+        GenericArrayType original = (GenericArrayType) toResolve;
+        Type componentType = original.getGenericComponentType();
+        Type newComponentType = resolveType(componentType);
+        return componentType == newComponentType
+            ? original
+            : Types.arrayOf(newComponentType);
+
+      } else if (toResolve instanceof ParameterizedType) {
+        ParameterizedType original = (ParameterizedType) toResolve;
+        Type ownerType = original.getOwnerType();
+        Type newOwnerType = resolveType(ownerType);
+        boolean changed = newOwnerType != ownerType;
+
+        Type[] args = original.getActualTypeArguments();
+        for (int t = 0, length = args.length; t < length; t++) {
+          Type resolvedTypeArgument = resolveType(args[t]);
+          if (resolvedTypeArgument != args[t]) {
+            if (!changed) {
+              args = args.clone();
+              changed = true;
+            }
+            args[t] = resolvedTypeArgument;
+          }
+        }
+
+        return changed
+            ? Types.newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args)
+            : original;
+
+      } else if (toResolve instanceof WildcardType) {
+        WildcardType original = (WildcardType) toResolve;
+        Type[] originalLowerBound = original.getLowerBounds();
+        Type[] originalUpperBound = original.getUpperBounds();
+
+        if (originalLowerBound.length == 1) {
+          Type lowerBound = resolveType(originalLowerBound[0]);
+          if (lowerBound != originalLowerBound[0]) {
+            return Types.supertypeOf(lowerBound);
+          }
+        } else if (originalUpperBound.length == 1) {
+          Type upperBound = resolveType(originalUpperBound[0]);
+          if (upperBound != originalUpperBound[0]) {
+            return Types.subtypeOf(upperBound);
+          }
+        }
+        return original;
+
+      } else {
+        return toResolve;
+      }
+    }
+  }
+
+  /**
+   * Returns the generic form of {@code supertype}. For example, if this is {@code
+   * ArrayList<String>}, this returns {@code Iterable<String>} given the input {@code
+   * Iterable.class}.
+   *
+   * @param supertype a superclass of, or interface implemented by, this.
+   * @since 2.0
+   */
+  public TypeLiteral<?> getSupertype(Class<?> supertype) {
+    checkArgument(supertype.isAssignableFrom(rawType),
+        "%s is not a supertype of %s", supertype, this.type);
+    return resolve(MoreTypes.getGenericSupertype(type, rawType, supertype));
+  }
+
+  /**
+   * Returns the resolved generic type of {@code field}.
+   *
+   * @param field a field defined by this or any superclass.
+   * @since 2.0
+   */
+  public TypeLiteral<?> getFieldType(Field field) {
+    checkArgument(field.getDeclaringClass().isAssignableFrom(rawType),
+        "%s is not defined by a supertype of %s", field, type);
+    return resolve(field.getGenericType());
+  }
+
+  /**
+   * Returns the resolved generic parameter types of {@code methodOrConstructor}.
+   *
+   * @param methodOrConstructor a method or constructor defined by this or any supertype.
+   * @since 2.0
+   */
+  public List<TypeLiteral<?>> getParameterTypes(Member methodOrConstructor) {
+    Type[] genericParameterTypes;
+
+    if (methodOrConstructor instanceof Method) {
+      Method method = (Method) methodOrConstructor;
+      checkArgument(method.getDeclaringClass().isAssignableFrom(rawType),
+          "%s is not defined by a supertype of %s", method, type);
+      genericParameterTypes = method.getGenericParameterTypes();
+
+    } else if (methodOrConstructor instanceof Constructor) {
+      Constructor<?> constructor = (Constructor<?>) methodOrConstructor;
+      checkArgument(constructor.getDeclaringClass().isAssignableFrom(rawType),
+          "%s does not construct a supertype of %s", constructor, type);
+      genericParameterTypes = constructor.getGenericParameterTypes();
+
+    } else {
+      throw new IllegalArgumentException("Not a method or a constructor: " + methodOrConstructor);
+    }
+
+    return resolveAll(genericParameterTypes);
+  }
+
+  /**
+   * Returns the resolved generic exception types thrown by {@code constructor}.
+   *
+   * @param methodOrConstructor a method or constructor defined by this or any supertype.
+   * @since 2.0
+   */
+  public List<TypeLiteral<?>> getExceptionTypes(Member methodOrConstructor) {
+    Type[] genericExceptionTypes;
+
+    if (methodOrConstructor instanceof Method) {
+      Method method = (Method) methodOrConstructor;
+      checkArgument(method.getDeclaringClass().isAssignableFrom(rawType),
+          "%s is not defined by a supertype of %s", method, type);
+      genericExceptionTypes = method.getGenericExceptionTypes();
+
+    } else if (methodOrConstructor instanceof Constructor) {
+      Constructor<?> constructor = (Constructor<?>) methodOrConstructor;
+      checkArgument(constructor.getDeclaringClass().isAssignableFrom(rawType),
+          "%s does not construct a supertype of %s", constructor, type);
+      genericExceptionTypes = constructor.getGenericExceptionTypes();
+
+    } else {
+      throw new IllegalArgumentException("Not a method or a constructor: " + methodOrConstructor);
+    }
+
+    return resolveAll(genericExceptionTypes);
+  }
+
+  /**
+   * Returns the resolved generic return type of {@code method}.
+   *
+   * @param method a method defined by this or any supertype.
+   * @since 2.0
+   */
+  public TypeLiteral<?> getReturnType(Method method) {
+    checkArgument(method.getDeclaringClass().isAssignableFrom(rawType),
+        "%s is not defined by a supertype of %s", method, type);
+    return resolve(method.getGenericReturnType());
+  }
+}
diff --git a/core/src/com/google/inject/binder/AnnotatedBindingBuilder.java b/core/src/com/google/inject/binder/AnnotatedBindingBuilder.java
new file mode 100644
index 0000000..5b430c3
--- /dev/null
+++ b/core/src/com/google/inject/binder/AnnotatedBindingBuilder.java
@@ -0,0 +1,38 @@
+/**
+ * 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 com.google.inject.binder;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * See the EDSL examples at {@link com.google.inject.Binder}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public interface AnnotatedBindingBuilder<T> extends LinkedBindingBuilder<T> {
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  LinkedBindingBuilder<T> annotatedWith(
+      Class<? extends Annotation> annotationType);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  LinkedBindingBuilder<T> annotatedWith(Annotation annotation);
+}
diff --git a/core/src/com/google/inject/binder/AnnotatedConstantBindingBuilder.java b/core/src/com/google/inject/binder/AnnotatedConstantBindingBuilder.java
new file mode 100644
index 0000000..417027f
--- /dev/null
+++ b/core/src/com/google/inject/binder/AnnotatedConstantBindingBuilder.java
@@ -0,0 +1,38 @@
+/**
+ * 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 com.google.inject.binder;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * See the EDSL examples at {@link com.google.inject.Binder}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public interface AnnotatedConstantBindingBuilder {
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  ConstantBindingBuilder annotatedWith(
+      Class<? extends Annotation> annotationType);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  ConstantBindingBuilder annotatedWith(Annotation annotation);
+}
diff --git a/core/src/com/google/inject/binder/AnnotatedElementBuilder.java b/core/src/com/google/inject/binder/AnnotatedElementBuilder.java
new file mode 100644
index 0000000..f6feddf
--- /dev/null
+++ b/core/src/com/google/inject/binder/AnnotatedElementBuilder.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 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.inject.binder;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * See the EDSL examples at {@link com.google.inject.Binder}.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface AnnotatedElementBuilder {
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  void annotatedWith(Class<? extends Annotation> annotationType);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  void annotatedWith(Annotation annotation);
+}
diff --git a/core/src/com/google/inject/binder/ConstantBindingBuilder.java b/core/src/com/google/inject/binder/ConstantBindingBuilder.java
new file mode 100644
index 0000000..7ddbcf9
--- /dev/null
+++ b/core/src/com/google/inject/binder/ConstantBindingBuilder.java
@@ -0,0 +1,80 @@
+/*
+ * 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 com.google.inject.binder;
+
+/**
+ * Binds to a constant value.
+ */
+public interface ConstantBindingBuilder {
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(String value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(int value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(long value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(boolean value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(double value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(float value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(short value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(char value);
+
+  /**
+   * Binds constant to the given value.
+   * 
+   * @since 3.0
+   */
+  void to(byte value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  void to(Class<?> value);
+
+  /**
+   * Binds constant to the given value.
+   */
+  <E extends Enum<E>> void to(E value);
+}
diff --git a/core/src/com/google/inject/binder/LinkedBindingBuilder.java b/core/src/com/google/inject/binder/LinkedBindingBuilder.java
new file mode 100644
index 0000000..99ea185
--- /dev/null
+++ b/core/src/com/google/inject/binder/LinkedBindingBuilder.java
@@ -0,0 +1,101 @@
+/**
+ * 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 com.google.inject.binder;
+
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * See the EDSL examples at {@link com.google.inject.Binder}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public interface LinkedBindingBuilder<T> extends ScopedBindingBuilder {
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  ScopedBindingBuilder to(Class<? extends T> implementation);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  ScopedBindingBuilder to(TypeLiteral<? extends T> implementation);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  ScopedBindingBuilder to(Key<? extends T> targetKey);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   *
+   * @see com.google.inject.Injector#injectMembers
+   */
+  void toInstance(T instance);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   *
+   * @see com.google.inject.Injector#injectMembers
+   */
+  ScopedBindingBuilder toProvider(Provider<? extends T> provider);
+  
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   *
+   * @see com.google.inject.Injector#injectMembers
+   * @since 4.0
+   */
+  ScopedBindingBuilder toProvider(javax.inject.Provider<? extends T> provider);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  ScopedBindingBuilder toProvider(
+      Class<? extends javax.inject.Provider<? extends T>> providerType);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  ScopedBindingBuilder toProvider(
+      TypeLiteral<? extends javax.inject.Provider<? extends T>> providerType);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  ScopedBindingBuilder toProvider(
+      Key<? extends javax.inject.Provider<? extends T>> providerKey);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   * 
+   * @since 3.0
+   */
+  <S extends T> ScopedBindingBuilder toConstructor(Constructor<S> constructor);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   * 
+   * @since 3.0
+   */
+  <S extends T> ScopedBindingBuilder toConstructor(
+      Constructor<S> constructor, TypeLiteral<? extends S> type);
+}
diff --git a/core/src/com/google/inject/binder/ScopedBindingBuilder.java b/core/src/com/google/inject/binder/ScopedBindingBuilder.java
new file mode 100644
index 0000000..ceb8497
--- /dev/null
+++ b/core/src/com/google/inject/binder/ScopedBindingBuilder.java
@@ -0,0 +1,47 @@
+/**
+ * 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 com.google.inject.binder;
+
+import com.google.inject.Scope;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * See the EDSL examples at {@link com.google.inject.Binder}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public interface ScopedBindingBuilder {
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  void in(Class<? extends Annotation> scopeAnnotation);
+
+  /**
+   * See the EDSL examples at {@link com.google.inject.Binder}.
+   */
+  void in(Scope scope);
+
+  /**
+   * Instructs the {@link com.google.inject.Injector} to eagerly initialize this
+   * singleton-scoped binding upon creation. Useful for application
+   * initialization logic.  See the EDSL examples at
+   * {@link com.google.inject.Binder}.
+   */
+  void asEagerSingleton();
+}
diff --git a/core/src/com/google/inject/binder/package-info.java b/core/src/com/google/inject/binder/package-info.java
new file mode 100644
index 0000000..57ed875
--- /dev/null
+++ b/core/src/com/google/inject/binder/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Interfaces which make up {@link com.google.inject.Binder}'s
+ * expression language.
+ */
+package com.google.inject.binder;
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/AbstractBindingBuilder.java b/core/src/com/google/inject/internal/AbstractBindingBuilder.java
new file mode 100644
index 0000000..e803b75
--- /dev/null
+++ b/core/src/com/google/inject/internal/AbstractBindingBuilder.java
@@ -0,0 +1,132 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.Scope;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.InstanceBinding;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+/**
+ * Bind a value or constant.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public abstract class AbstractBindingBuilder<T> {
+
+  public static final String IMPLEMENTATION_ALREADY_SET = "Implementation is set more than once.";
+  public static final String SINGLE_INSTANCE_AND_SCOPE
+      = "Setting the scope is not permitted when binding to a single instance.";
+  public static final String SCOPE_ALREADY_SET = "Scope is set more than once.";
+  public static final String BINDING_TO_NULL = "Binding to null instances is not allowed. "
+      + "Use toProvider(Providers.of(null)) if this is your intended behaviour.";
+  public static final String CONSTANT_VALUE_ALREADY_SET = "Constant value is set more than once.";
+  public static final String ANNOTATION_ALREADY_SPECIFIED
+      = "More than one annotation is specified for this binding.";
+
+  protected static final Key<?> NULL_KEY = Key.get(Void.class);
+
+  protected List<Element> elements;
+  protected int position;
+  protected final Binder binder;
+  private BindingImpl<T> binding;
+
+  public AbstractBindingBuilder(Binder binder, List<Element> elements, Object source, Key<T> key) {
+    this.binder = binder;
+    this.elements = elements;
+    this.position = elements.size();
+    this.binding = new UntargettedBindingImpl<T>(source, key, Scoping.UNSCOPED);
+    elements.add(position, this.binding);
+  }
+
+  protected BindingImpl<T> getBinding() {
+    return binding;
+  }
+
+  protected BindingImpl<T> setBinding(BindingImpl<T> binding) {
+    this.binding = binding;
+    elements.set(position, binding);
+    return binding;
+  }
+
+  /** Sets the binding to a copy with the specified annotation on the bound key */
+  protected BindingImpl<T> annotatedWithInternal(Class<? extends Annotation> annotationType) {
+    checkNotNull(annotationType, "annotationType");
+    checkNotAnnotated();
+    return setBinding(binding.withKey(
+        Key.get(this.binding.getKey().getTypeLiteral(), annotationType)));
+  }
+
+  /** Sets the binding to a copy with the specified annotation on the bound key */
+  protected BindingImpl<T> annotatedWithInternal(Annotation annotation) {
+    checkNotNull(annotation, "annotation");
+    checkNotAnnotated();
+    return setBinding(binding.withKey(
+        Key.get(this.binding.getKey().getTypeLiteral(), annotation)));
+  }
+
+  public void in(final Class<? extends Annotation> scopeAnnotation) {
+    checkNotNull(scopeAnnotation, "scopeAnnotation");
+    checkNotScoped();
+    setBinding(getBinding().withScoping(Scoping.forAnnotation(scopeAnnotation)));
+  }
+
+  public void in(final Scope scope) {
+    checkNotNull(scope, "scope");
+    checkNotScoped();
+    setBinding(getBinding().withScoping(Scoping.forInstance(scope)));
+  }
+
+  public void asEagerSingleton() {
+    checkNotScoped();
+    setBinding(getBinding().withScoping(Scoping.EAGER_SINGLETON));
+  }
+
+  protected boolean keyTypeIsSet() {
+    return !Void.class.equals(binding.getKey().getTypeLiteral().getType());
+  }
+
+  protected void checkNotTargetted() {
+    if (!(binding instanceof UntargettedBindingImpl)) {
+      binder.addError(IMPLEMENTATION_ALREADY_SET);
+    }
+  }
+
+  protected void checkNotAnnotated() {
+    if (binding.getKey().getAnnotationType() != null) {
+      binder.addError(ANNOTATION_ALREADY_SPECIFIED);
+    }
+  }
+
+  protected void checkNotScoped() {
+    // Scoping isn't allowed when we have only one instance.
+    if (binding instanceof InstanceBinding) {
+      binder.addError(SINGLE_INSTANCE_AND_SCOPE);
+      return;
+    }
+
+    if (binding.getScoping().isExplicitlyScoped()) {
+      binder.addError(SCOPE_ALREADY_SET);
+    }
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/AbstractBindingProcessor.java b/core/src/com/google/inject/internal/AbstractBindingProcessor.java
new file mode 100644
index 0000000..e1a0bba
--- /dev/null
+++ b/core/src/com/google/inject/internal/AbstractBindingProcessor.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.internal;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+
+import java.util.Set;
+
+/**
+ * Guarantees that processing of Binding elements happens in a sane way.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+abstract class AbstractBindingProcessor extends AbstractProcessor {
+
+  // It's unfortunate that we have to maintain a blacklist of specific
+  // classes, but we can't easily block the whole package because of
+  // all our unit tests.
+  private static final Set<Class<?>> FORBIDDEN_TYPES = ImmutableSet.<Class<?>>of(
+      AbstractModule.class,
+      Binder.class,
+      Binding.class,
+      Injector.class,
+      Key.class,
+      MembersInjector.class,
+      Module.class,
+      Provider.class,
+      Scope.class,
+      Stage.class,
+      TypeLiteral.class);
+  
+  protected final ProcessedBindingData bindingData;
+  
+  AbstractBindingProcessor(Errors errors, ProcessedBindingData bindingData) {
+    super(errors);
+    this.bindingData = bindingData;
+  }
+
+  protected <T> UntargettedBindingImpl<T> invalidBinding(
+      InjectorImpl injector, Key<T> key, Object source) {
+    return new UntargettedBindingImpl<T>(injector, key, source);
+  }
+  
+  protected void putBinding(BindingImpl<?> binding) {
+    Key<?> key = binding.getKey();
+
+    Class<?> rawType = key.getTypeLiteral().getRawType();
+    if (FORBIDDEN_TYPES.contains(rawType)) {
+      errors.cannotBindToGuiceType(rawType.getSimpleName());
+      return;
+    }
+
+    BindingImpl<?> original = injector.getExistingBinding(key);
+    if (original != null) {
+      // If it failed because of an explicit duplicate binding...
+      if (injector.state.getExplicitBinding(key) != null) {
+        try {
+          if(!isOkayDuplicate(original, binding, injector.state)) {
+            errors.bindingAlreadySet(key, original.getSource());
+            return;
+          }
+        } catch(Throwable t) {
+          errors.errorCheckingDuplicateBinding(key, original.getSource(), t);
+          return;
+        }
+      } else {
+        // Otherwise, it failed because of a duplicate JIT binding
+        // in the parent
+        errors.jitBindingAlreadySet(key);
+        return;
+      }
+    }
+
+    // prevent the parent from creating a JIT binding for this key
+    injector.state.parent().blacklist(key, injector.state, binding.getSource());
+    injector.state.putBinding(key, binding);
+  }
+
+  /**
+   * We tolerate duplicate bindings if one exposes the other or if the two bindings
+   * are considered duplicates (see {@link Bindings#areDuplicates(BindingImpl, BindingImpl)}.
+   *
+   * @param original the binding in the parent injector (candidate for an exposing binding)
+   * @param binding the binding to check (candidate for the exposed binding)
+   */
+  private boolean isOkayDuplicate(BindingImpl<?> original, BindingImpl<?> binding, State state) {
+    if (original instanceof ExposedBindingImpl) {
+      ExposedBindingImpl exposed = (ExposedBindingImpl) original;
+      InjectorImpl exposedFrom = (InjectorImpl) exposed.getPrivateElements().getInjector();
+      return (exposedFrom == binding.getInjector());
+    } else {
+      original = (BindingImpl<?>)state.getExplicitBindingsThisLevel().get(binding.getKey());
+      // If no original at this level, the original was on a parent, and we don't
+      // allow deduplication between parents & children.
+      if(original == null) {
+        return false;
+      } else {
+        return original.equals(binding);
+      }
+    }
+  }
+  
+  private <T> void validateKey(Object source, Key<T> key) {
+    Annotations.checkForMisplacedScopeAnnotations(
+        key.getTypeLiteral().getRawType(), source, errors);
+  }
+  
+  /** 
+   * Processor for visiting bindings.  Each overriden method that wants to
+   * actually process the binding should call prepareBinding first.
+   */
+  abstract class Processor<T, V> extends DefaultBindingTargetVisitor<T, V> {
+    final Object source;
+    final Key<T> key;
+    final Class<? super T> rawType;
+    Scoping scoping;
+    
+    Processor(BindingImpl<T> binding) {
+      source = binding.getSource();
+      key = binding.getKey();
+      rawType = key.getTypeLiteral().getRawType();
+      scoping = binding.getScoping();
+    }
+    
+    protected void prepareBinding() {      
+      validateKey(source, key);
+      scoping = Scoping.makeInjectable(scoping, injector, errors);
+    }
+
+    protected void scheduleInitialization(final BindingImpl<?> binding) {
+      bindingData.addUninitializedBinding(new Runnable() {
+        public void run() {
+          try {
+            binding.getInjector().initializeBinding(binding, errors.withSource(source));
+          } catch (ErrorsException e) {
+            errors.merge(e.getErrors());
+          }
+        }
+      });
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/AbstractProcessor.java b/core/src/com/google/inject/internal/AbstractProcessor.java
new file mode 100644
index 0000000..2697a99
--- /dev/null
+++ b/core/src/com/google/inject/internal/AbstractProcessor.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.spi.DefaultElementVisitor;
+import com.google.inject.spi.Element;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Abstract base class for creating an injector from module elements.
+ *
+ * <p>Extending classes must return {@code true} from any overridden
+ * {@code visit*()} methods, in order for the element processor to remove the
+ * handled element.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+abstract class AbstractProcessor extends DefaultElementVisitor<Boolean> {
+
+  protected Errors errors;
+  protected InjectorImpl injector;
+
+  protected AbstractProcessor(Errors errors) {
+    this.errors = errors;
+  }
+
+  public void process(Iterable<InjectorShell> isolatedInjectorBuilders) {
+    for (InjectorShell injectorShell : isolatedInjectorBuilders) {
+      process(injectorShell.getInjector(), injectorShell.getElements());
+    }
+  }
+
+  public void process(InjectorImpl injector, List<Element> elements) {
+    Errors errorsAnyElement = this.errors;
+    this.injector = injector;
+    try {
+      for (Iterator<Element> i = elements.iterator(); i.hasNext(); ) {
+        Element element = i.next();
+        this.errors = errorsAnyElement.withSource(element.getSource());
+        Boolean allDone = element.acceptVisitor(this);
+        if (allDone) {
+          i.remove();
+        }
+      }
+    } finally {
+      this.errors = errorsAnyElement;
+      this.injector = null;
+    }
+  }
+  
+  @Override
+  protected Boolean visitOther(Element element) {
+    return false;
+  }
+}
diff --git a/core/src/com/google/inject/internal/Annotations.java b/core/src/com/google/inject/internal/Annotations.java
new file mode 100644
index 0000000..4c994a9
--- /dev/null
+++ b/core/src/com/google/inject/internal/Annotations.java
@@ -0,0 +1,341 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Joiner.MapJoiner;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Key;
+import com.google.inject.ScopeAnnotation;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.util.Classes;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+import javax.inject.Qualifier;
+
+/**
+ * Annotation utilities.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class Annotations {
+
+  /**
+   * Returns {@code true} if the given annotation type has no attributes.
+   */
+  public static boolean isMarker(Class<? extends Annotation> annotationType) {
+    return annotationType.getDeclaredMethods().length == 0;
+  }
+
+  public static boolean isAllDefaultMethods(Class<? extends Annotation> annotationType) {
+    boolean hasMethods = false;
+    for (Method m : annotationType.getDeclaredMethods()) {
+      hasMethods = true;
+      if (m.getDefaultValue() == null) {
+        return false;
+      }
+    }
+    return hasMethods;
+  }
+
+  private static final LoadingCache<Class<? extends Annotation>, Annotation> cache =
+      CacheBuilder.newBuilder().weakKeys().build(
+          new CacheLoader<Class<? extends Annotation>, Annotation>() {
+            @Override
+            public Annotation load(Class<? extends Annotation> input) {
+              return generateAnnotationImpl(input);
+            }
+          });
+
+  /**
+   * Generates an Annotation for the annotation class. Requires that the annotation is all
+   * optionals.
+   */
+  public static <T extends Annotation> T generateAnnotation(Class<T> annotationType) {
+    Preconditions.checkState(
+        isAllDefaultMethods(annotationType), "%s is not all default methods", annotationType);
+    return (T)cache.getUnchecked(annotationType);
+  }
+
+  private static <T extends Annotation> T generateAnnotationImpl(final Class<T> annotationType) {
+    final Map<String, Object> members = resolveMembers(annotationType);
+    return annotationType.cast(Proxy.newProxyInstance(
+        annotationType.getClassLoader(),
+        new Class<?>[] { annotationType },
+        new InvocationHandler() {
+          @Override
+          public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
+            String name = method.getName();
+            if (name.equals("annotationType")) {
+              return annotationType;
+            } else if (name.equals("toString")) {
+              return annotationToString(annotationType, members);
+            } else if (name.equals("hashCode")) {
+              return annotationHashCode(annotationType, members);
+            } else if (name.equals("equals")) {
+              return annotationEquals(annotationType, members, args[0]);
+            } else {
+              return members.get(name);
+            }
+          }
+        }));
+  }
+
+  private static ImmutableMap<String, Object> resolveMembers(
+      Class<? extends Annotation> annotationType) {
+    ImmutableMap.Builder<String, Object> result = ImmutableMap.builder();
+    for (Method method : annotationType.getDeclaredMethods()) {
+      result.put(method.getName(), method.getDefaultValue());
+    }
+    return result.build();
+  }
+
+  /** Implements {@link Annotation#equals}. */
+  private static boolean annotationEquals(Class<? extends Annotation> type,
+      Map<String, Object> members, Object other) throws Exception {
+    if (!type.isInstance(other)) {
+      return false;
+    }
+    for (Method method : type.getDeclaredMethods()) {
+      String name = method.getName();
+      if (!Arrays.deepEquals(
+          new Object[] {method.invoke(other)}, new Object[] {members.get(name)})) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /** Implements {@link Annotation#hashCode}. */
+  private static int annotationHashCode(Class<? extends Annotation> type,
+      Map<String, Object> members) throws Exception {
+    int result = 0;
+    for (Method method : type.getDeclaredMethods()) {
+      String name = method.getName();
+      Object value = members.get(name);
+      result += (127 * name.hashCode()) ^ (Arrays.deepHashCode(new Object[] {value}) - 31);
+    }
+    return result;
+  }
+
+  private static final MapJoiner JOINER = Joiner.on(", ").withKeyValueSeparator("=");
+
+  private static final Function<Object, String> DEEP_TO_STRING_FN = new Function<Object, String>() {
+    @Override
+    public String apply(Object arg) {
+      String s = Arrays.deepToString(new Object[] {arg});
+      return s.substring(1, s.length() - 1); // cut off brackets
+    }
+  };
+
+  /** Implements {@link Annotation#toString}. */
+  private static String annotationToString(Class<? extends Annotation> type,
+      Map<String, Object> members) throws Exception {
+    StringBuilder sb = new StringBuilder().append("@").append(type.getName()).append("(");
+    JOINER.appendTo(sb, Maps.transformValues(members, DEEP_TO_STRING_FN));
+    return sb.append(")").toString();
+  }
+
+  /**
+   * Returns true if the given annotation is retained at runtime.
+   */
+  public static boolean isRetainedAtRuntime(Class<? extends Annotation> annotationType) {
+    Retention retention = annotationType.getAnnotation(Retention.class);
+    return retention != null && retention.value() == RetentionPolicy.RUNTIME;
+  }
+
+  /** Returns the scope annotation on {@code type}, or null if none is specified. */
+  public static Class<? extends Annotation> findScopeAnnotation(
+      Errors errors, Class<?> implementation) {
+    return findScopeAnnotation(errors, implementation.getAnnotations());
+  }
+
+  /** Returns the scoping annotation, or null if there isn't one. */
+  public static Class<? extends Annotation> findScopeAnnotation(Errors errors, Annotation[] annotations) {
+    Class<? extends Annotation> found = null;
+
+    for (Annotation annotation : annotations) {
+      Class<? extends Annotation> annotationType = annotation.annotationType();
+      if (isScopeAnnotation(annotationType)) {
+        if (found != null) {
+          errors.duplicateScopeAnnotations(found, annotationType);
+        } else {
+          found = annotationType;
+        }
+      }
+    }
+
+    return found;
+  }
+
+  static boolean containsComponentAnnotation(Annotation[] annotations) {
+    for (Annotation annotation : annotations) {
+      // TODO(user): Should we scope this down to dagger.Component?
+      if (annotation.annotationType().getSimpleName().equals("Component")) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Checks for the presence of annotations. Caches results because Android doesn't.
+   */
+  static class AnnotationChecker {
+    private final Collection<Class<? extends Annotation>> annotationTypes;
+
+    /** Returns true if the given class has one of the desired annotations. */
+    private CacheLoader<Class<? extends Annotation>, Boolean> hasAnnotations =
+        new CacheLoader<Class<? extends Annotation>, Boolean>() {
+      public Boolean load(Class<? extends Annotation> annotationType) {
+        for (Annotation annotation : annotationType.getAnnotations()) {
+          if (annotationTypes.contains(annotation.annotationType())) {
+            return true;
+          }
+        }
+        return false;
+      }
+    };
+
+    final LoadingCache<Class<? extends Annotation>, Boolean> cache = CacheBuilder.newBuilder().weakKeys()
+        .build(hasAnnotations);
+
+    /**
+     * Constructs a new checker that looks for annotations of the given types.
+     */
+    AnnotationChecker(Collection<Class<? extends Annotation>> annotationTypes) {
+      this.annotationTypes = annotationTypes;
+    }
+
+    /**
+     * Returns true if the given type has one of the desired annotations.
+     */
+    boolean hasAnnotations(Class<? extends Annotation> annotated) {
+      return cache.getUnchecked(annotated);
+    }
+  }
+
+  private static final AnnotationChecker scopeChecker = new AnnotationChecker(
+      Arrays.asList(ScopeAnnotation.class, javax.inject.Scope.class));
+
+  public static boolean isScopeAnnotation(Class<? extends Annotation> annotationType) {
+    return scopeChecker.hasAnnotations(annotationType);
+  }
+
+  /**
+   * Adds an error if there is a misplaced annotations on {@code type}. Scoping
+   * annotations are not allowed on abstract classes or interfaces.
+   */
+  public static void checkForMisplacedScopeAnnotations(
+      Class<?> type, Object source, Errors errors) {
+    if (Classes.isConcrete(type)) {
+      return;
+    }
+
+    Class<? extends Annotation> scopeAnnotation = findScopeAnnotation(errors, type);
+    if (scopeAnnotation != null
+        // We let Dagger Components through to aid migrations.
+        && !containsComponentAnnotation(type.getAnnotations())) {
+      errors.withSource(type).scopeAnnotationOnAbstractType(scopeAnnotation, type, source);
+    }
+  }
+
+  /** Gets a key for the given type, member and annotations. */
+  public static Key<?> getKey(TypeLiteral<?> type, Member member, Annotation[] annotations,
+      Errors errors) throws ErrorsException {
+    int numErrorsBefore = errors.size();
+    Annotation found = findBindingAnnotation(errors, member, annotations);
+    errors.throwIfNewErrors(numErrorsBefore);
+    return found == null ? Key.get(type) : Key.get(type, found);
+  }
+
+  /**
+   * Returns the binding annotation on {@code member}, or null if there isn't one.
+   */
+  public static Annotation findBindingAnnotation(
+      Errors errors, Member member, Annotation[] annotations) {
+    Annotation found = null;
+
+    for (Annotation annotation : annotations) {
+      Class<? extends Annotation> annotationType = annotation.annotationType();
+      if (isBindingAnnotation(annotationType)) {
+        if (found != null) {
+          errors.duplicateBindingAnnotations(member, found.annotationType(), annotationType);
+        } else {
+          found = annotation;
+        }
+      }
+    }
+
+    return found;
+  }
+
+  private static final AnnotationChecker bindingAnnotationChecker = new AnnotationChecker(
+      Arrays.asList(BindingAnnotation.class, Qualifier.class));
+
+  /**
+   * Returns true if annotations of the specified type are binding annotations.
+   */
+  public static boolean isBindingAnnotation(Class<? extends Annotation> annotationType) {
+    return bindingAnnotationChecker.hasAnnotations(annotationType);
+  }
+
+  /**
+   * If the annotation is an instance of {@code javax.inject.Named}, canonicalizes to
+   * com.google.guice.name.Named.  Returns the given annotation otherwise.
+   */
+  public static Annotation canonicalizeIfNamed(Annotation annotation) {
+    if(annotation instanceof javax.inject.Named) {
+      return Names.named(((javax.inject.Named)annotation).value());
+    } else {
+      return annotation;
+    }
+  }
+
+  /**
+   * If the annotation is the class {@code javax.inject.Named}, canonicalizes to
+   * com.google.guice.name.Named. Returns the given annotation class otherwise.
+   */
+  public static Class<? extends Annotation> canonicalizeIfNamed(
+      Class<? extends Annotation> annotationType) {
+    if (annotationType == javax.inject.Named.class) {
+      return Named.class;
+    } else {
+      return annotationType;
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/BindingBuilder.java b/core/src/com/google/inject/internal/BindingBuilder.java
new file mode 100644
index 0000000..36c31ff
--- /dev/null
+++ b/core/src/com/google/inject/internal/BindingBuilder.java
@@ -0,0 +1,183 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.ScopedBindingBuilder;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.Message;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Bind a non-constant key.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class BindingBuilder<T> extends AbstractBindingBuilder<T>
+    implements AnnotatedBindingBuilder<T> {
+
+  public BindingBuilder(Binder binder, List<Element> elements, Object source, Key<T> key) {
+    super(binder, elements, source, key);
+  }
+
+  public BindingBuilder<T> annotatedWith(Class<? extends Annotation> annotationType) {
+    annotatedWithInternal(annotationType);
+    return this;
+  }
+
+  public BindingBuilder<T> annotatedWith(Annotation annotation) {
+    annotatedWithInternal(annotation);
+    return this;
+  }
+
+  public BindingBuilder<T> to(Class<? extends T> implementation) {
+    return to(Key.get(implementation));
+  }
+
+  public BindingBuilder<T> to(TypeLiteral<? extends T> implementation) {
+    return to(Key.get(implementation));
+  }
+
+  public BindingBuilder<T> to(Key<? extends T> linkedKey) {
+    checkNotNull(linkedKey, "linkedKey");
+    checkNotTargetted();
+    BindingImpl<T> base = getBinding();
+    setBinding(new LinkedBindingImpl<T>(
+        base.getSource(), base.getKey(), base.getScoping(), linkedKey));
+    return this;
+  }
+
+  public void toInstance(T instance) {
+    checkNotTargetted();
+
+    // lookup the injection points, adding any errors to the binder's errors list
+    Set<InjectionPoint> injectionPoints;
+    if (instance != null) {
+      try {
+        injectionPoints = InjectionPoint.forInstanceMethodsAndFields(instance.getClass());
+      } catch (ConfigurationException e) {
+        copyErrorsToBinder(e);
+        injectionPoints = e.getPartialValue();
+      }
+    } else {
+      binder.addError(BINDING_TO_NULL);
+      injectionPoints = ImmutableSet.of();
+    }
+
+    BindingImpl<T> base = getBinding();
+    setBinding(new InstanceBindingImpl<T>(
+        base.getSource(), base.getKey(), Scoping.EAGER_SINGLETON, injectionPoints, instance));
+  }
+
+  public BindingBuilder<T> toProvider(Provider<? extends T> provider) {
+    return toProvider((javax.inject.Provider<T>) provider);
+  }
+
+  public BindingBuilder<T> toProvider(javax.inject.Provider<? extends T> provider) {
+    checkNotNull(provider, "provider");
+    checkNotTargetted();
+
+    // lookup the injection points, adding any errors to the binder's errors list
+    Set<InjectionPoint> injectionPoints;
+    try {
+      injectionPoints = InjectionPoint.forInstanceMethodsAndFields(provider.getClass());
+    } catch (ConfigurationException e) {
+      copyErrorsToBinder(e);
+      injectionPoints = e.getPartialValue();
+    }
+
+    BindingImpl<T> base = getBinding();
+    setBinding(new ProviderInstanceBindingImpl<T>(
+        base.getSource(), base.getKey(), base.getScoping(), injectionPoints, provider));
+    return this;
+  }
+
+  public BindingBuilder<T> toProvider(
+      Class<? extends javax.inject.Provider<? extends T>> providerType) {
+    return toProvider(Key.get(providerType));
+  }
+
+  public BindingBuilder<T> toProvider(
+      TypeLiteral<? extends javax.inject.Provider<? extends T>> providerType) {
+    return toProvider(Key.get(providerType));
+  }
+
+  public BindingBuilder<T> toProvider(
+      Key<? extends javax.inject.Provider<? extends T>> providerKey) {
+    checkNotNull(providerKey, "providerKey");
+    checkNotTargetted();
+
+    BindingImpl<T> base = getBinding();
+    setBinding(new LinkedProviderBindingImpl<T>(
+        base.getSource(), base.getKey(), base.getScoping(), providerKey));
+    return this;
+  }
+
+  public <S extends T> ScopedBindingBuilder toConstructor(Constructor<S> constructor) {
+    return toConstructor(constructor, TypeLiteral.get(constructor.getDeclaringClass()));
+  }
+
+  public <S extends T> ScopedBindingBuilder toConstructor(Constructor<S> constructor,
+      TypeLiteral<? extends S> type) {
+    checkNotNull(constructor, "constructor");
+    checkNotNull(type, "type");
+    checkNotTargetted();
+
+    BindingImpl<T> base = getBinding();
+
+    Set<InjectionPoint> injectionPoints;
+    try {
+      injectionPoints = InjectionPoint.forInstanceMethodsAndFields(type);
+    } catch (ConfigurationException e) {
+      copyErrorsToBinder(e);
+      injectionPoints = e.getPartialValue();
+    }
+
+    try {
+      InjectionPoint constructorPoint = InjectionPoint.forConstructor(constructor, type);
+      setBinding(new ConstructorBindingImpl<T>(base.getKey(), base.getSource(), base.getScoping(),
+          constructorPoint, injectionPoints));
+    } catch (ConfigurationException e) {
+      copyErrorsToBinder(e);
+    }
+
+    return this;
+  }
+  
+  @Override public String toString() {
+    return "BindingBuilder<" + getBinding().getKey().getTypeLiteral() + ">";
+  }
+
+  private void copyErrorsToBinder(ConfigurationException e) {
+    for (Message message : e.getErrorMessages()) {
+      binder.addError(message);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/BindingImpl.java b/core/src/com/google/inject/internal/BindingImpl.java
new file mode 100644
index 0000000..3228e3d
--- /dev/null
+++ b/core/src/com/google/inject/internal/BindingImpl.java
@@ -0,0 +1,119 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.spi.BindingScopingVisitor;
+import com.google.inject.spi.ElementVisitor;
+import com.google.inject.spi.InstanceBinding;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public abstract class BindingImpl<T> implements Binding<T> {
+
+  private final InjectorImpl injector;
+  private final Key<T> key;
+  private final Object source;
+  private final Scoping scoping;
+  private final InternalFactory<? extends T> internalFactory;
+
+  public BindingImpl(InjectorImpl injector, Key<T> key, Object source,
+      InternalFactory<? extends T> internalFactory, Scoping scoping) {
+    this.injector = injector;
+    this.key = key;
+    this.source = source;
+    this.internalFactory = internalFactory;
+    this.scoping = scoping;
+  }
+
+  protected BindingImpl(Object source, Key<T> key, Scoping scoping) {
+    this.internalFactory = null;
+    this.injector = null;
+    this.source = source;
+    this.key = key;
+    this.scoping = scoping;
+  }
+
+  public Key<T> getKey() {
+    return key;
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  private volatile Provider<T> provider;
+
+  public Provider<T> getProvider() {
+    if (provider == null) {
+      if (injector == null) {
+        throw new UnsupportedOperationException("getProvider() not supported for module bindings");
+      }
+
+      provider = injector.getProvider(key);
+    }
+    return provider;
+  }
+
+  public InternalFactory<? extends T> getInternalFactory() {
+    return internalFactory;
+  }
+
+  public Scoping getScoping() {
+    return scoping;
+  }
+
+  /**
+   * Is this a constant binding? This returns true for constant bindings as
+   * well as toInstance() bindings.
+   */
+  public boolean isConstant() {
+    return this instanceof InstanceBinding;
+  }
+
+  public <V> V acceptVisitor(ElementVisitor<V> visitor) {
+    return visitor.visit(this);
+  }
+
+  public <V> V acceptScopingVisitor(BindingScopingVisitor<V> visitor) {
+    return scoping.acceptVisitor(visitor);
+  }
+
+  protected BindingImpl<T> withScoping(Scoping scoping) {
+    throw new AssertionError();
+  }
+
+  protected BindingImpl<T> withKey(Key<T> key) {
+    throw new AssertionError();
+  }
+  
+  @Override public String toString() {
+    return Objects.toStringHelper(Binding.class)
+        .add("key", key)
+        .add("scope", scoping)
+        .add("source", source)
+        .toString();
+  }
+
+  public InjectorImpl getInjector() {
+    return injector;
+  }
+}
diff --git a/core/src/com/google/inject/internal/BindingProcessor.java b/core/src/com/google/inject/internal/BindingProcessor.java
new file mode 100644
index 0000000..b3c869e
--- /dev/null
+++ b/core/src/com/google/inject/internal/BindingProcessor.java
@@ -0,0 +1,197 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.spi.ConstructorBinding;
+import com.google.inject.spi.ConvertedConstantBinding;
+import com.google.inject.spi.ExposedBinding;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.LinkedKeyBinding;
+import com.google.inject.spi.PrivateElements;
+import com.google.inject.spi.ProviderBinding;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderKeyBinding;
+import com.google.inject.spi.UntargettedBinding;
+
+import java.util.Set;
+
+/**
+ * Handles {@link Binder#bind} and {@link Binder#bindConstant} elements.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class BindingProcessor extends AbstractBindingProcessor {
+
+  private final Initializer initializer;
+
+  BindingProcessor(Errors errors, Initializer initializer, ProcessedBindingData bindingData) {
+    super(errors, bindingData);
+    this.initializer = initializer;
+  }
+
+  @Override public <T> Boolean visit(Binding<T> command) {
+    Class<?> rawType = command.getKey().getTypeLiteral().getRawType();
+    if (Void.class.equals(rawType)) {
+      if (command instanceof ProviderInstanceBinding
+          && ((ProviderInstanceBinding) command).getUserSuppliedProvider()
+              instanceof ProviderMethod) {
+        errors.voidProviderMethod();
+      } else {
+        errors.missingConstantValues();
+      }
+      return true;
+    }
+    
+    if (rawType == Provider.class) {
+      errors.bindingToProvider();
+      return true;
+    }
+    
+    return command.acceptTargetVisitor(new Processor<T, Boolean>((BindingImpl<T>)command) {
+      @Override
+      public Boolean visit(ConstructorBinding<? extends T> binding) {
+        prepareBinding();
+        try {
+          ConstructorBindingImpl<T> onInjector = ConstructorBindingImpl.create(injector, key, 
+              binding.getConstructor(), source, scoping, errors, false, false);
+          scheduleInitialization(onInjector);
+          putBinding(onInjector);
+        } catch (ErrorsException e) {
+          errors.merge(e.getErrors());
+          putBinding(invalidBinding(injector, key, source));
+        }
+        return true;
+      }
+
+      @Override
+      public Boolean visit(InstanceBinding<? extends T> binding) {
+        prepareBinding();
+        Set<InjectionPoint> injectionPoints = binding.getInjectionPoints();
+        T instance = binding.getInstance();
+        @SuppressWarnings("unchecked") // safe to cast to binding<T> because
+                                       // the processor was constructed w/ it
+        Initializable<T> ref = initializer.requestInjection(
+            injector, instance, (Binding<T>) binding, source, injectionPoints);
+        ConstantFactory<? extends T> factory = new ConstantFactory<T>(ref);
+        InternalFactory<? extends T> scopedFactory
+            = Scoping.scope(key, injector, factory, source, scoping);
+        putBinding(new InstanceBindingImpl<T>(injector, key, source, scopedFactory, injectionPoints,
+            instance));
+        return true;
+      }
+
+      @Override
+      public Boolean visit(ProviderInstanceBinding<? extends T> binding) {
+        prepareBinding();
+        javax.inject.Provider<? extends T> provider = binding.getUserSuppliedProvider();
+        Set<InjectionPoint> injectionPoints = binding.getInjectionPoints();
+        Initializable<? extends javax.inject.Provider<? extends T>> initializable =
+            initializer.<javax.inject.Provider<? extends T>>requestInjection(
+                injector, provider, null, source, injectionPoints);
+        // always visited with Binding<T>
+        @SuppressWarnings("unchecked") 
+        InternalFactory<T> factory = new InternalFactoryToInitializableAdapter<T>(
+            initializable, source,
+            injector.provisionListenerStore.get((ProviderInstanceBinding<T>)binding));
+        InternalFactory<? extends T> scopedFactory
+            = Scoping.scope(key, injector, factory, source, scoping);
+        putBinding(new ProviderInstanceBindingImpl<T>(injector, key, source, scopedFactory, scoping,
+            provider, injectionPoints));
+        return true;
+      }
+
+      @Override
+      public Boolean visit(ProviderKeyBinding<? extends T> binding) {
+        prepareBinding();
+        Key<? extends javax.inject.Provider<? extends T>> providerKey = binding.getProviderKey();
+        // always visited with Binding<T>
+        @SuppressWarnings("unchecked") 
+        BoundProviderFactory<T> boundProviderFactory = new BoundProviderFactory<T>(
+            injector, providerKey, source,
+            injector.provisionListenerStore.get((ProviderKeyBinding<T>) binding));
+        bindingData.addCreationListener(boundProviderFactory);
+        InternalFactory<? extends T> scopedFactory = Scoping.scope(
+            key, injector, (InternalFactory<? extends T>) boundProviderFactory, source, scoping);
+        putBinding(new LinkedProviderBindingImpl<T>(
+            injector, key, source, scopedFactory, scoping, providerKey));
+        return true;
+      }
+
+      @Override
+      public Boolean visit(LinkedKeyBinding<? extends T> binding) {
+        prepareBinding();
+        Key<? extends T> linkedKey = binding.getLinkedKey();
+        if (key.equals(linkedKey)) {
+          errors.recursiveBinding();
+        }
+
+        FactoryProxy<T> factory = new FactoryProxy<T>(injector, key, linkedKey, source);
+        bindingData.addCreationListener(factory);
+        InternalFactory<? extends T> scopedFactory
+            = Scoping.scope(key, injector, factory, source, scoping);
+        putBinding(
+            new LinkedBindingImpl<T>(injector, key, source, scopedFactory, scoping, linkedKey));
+        return true;
+      }
+
+      @Override
+      public Boolean visit(UntargettedBinding<? extends T> untargetted) {
+        return false;
+      }
+
+      @Override
+      public Boolean visit(ExposedBinding<? extends T> binding) {
+        throw new IllegalArgumentException("Cannot apply a non-module element");
+      }
+      
+      @Override
+      public Boolean visit(ConvertedConstantBinding<? extends T> binding) {
+        throw new IllegalArgumentException("Cannot apply a non-module element");
+      }
+      
+      @Override
+      public Boolean visit(ProviderBinding<? extends T> binding) {
+        throw new IllegalArgumentException("Cannot apply a non-module element");
+      }
+      
+      @Override
+      protected Boolean visitOther(Binding<? extends T> binding) {
+        throw new IllegalStateException("BindingProcessor should override all visitations");
+      }
+    });
+  }
+
+  @Override public Boolean visit(PrivateElements privateElements) {
+    for (Key<?> key : privateElements.getExposedKeys()) {
+      bindExposed(privateElements, key);
+    }
+    return false; // leave the private elements for the PrivateElementsProcessor to handle
+  }
+
+  private <T> void bindExposed(PrivateElements privateElements, Key<T> key) {
+    ExposedKeyFactory<T> exposedKeyFactory = new ExposedKeyFactory<T>(key, privateElements);
+    bindingData.addCreationListener(exposedKeyFactory);
+    putBinding(new ExposedBindingImpl<T>(
+        injector, privateElements.getExposedSource(key), key, exposedKeyFactory, privateElements));
+  }
+}
diff --git a/core/src/com/google/inject/internal/BoundProviderFactory.java b/core/src/com/google/inject/internal/BoundProviderFactory.java
new file mode 100644
index 0000000..9f523df
--- /dev/null
+++ b/core/src/com/google/inject/internal/BoundProviderFactory.java
@@ -0,0 +1,81 @@
+/**
+ * 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 com.google.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Key;
+import com.google.inject.internal.InjectorImpl.JitLimitation;
+import com.google.inject.spi.Dependency;
+
+import javax.inject.Provider;
+
+/**
+ * Delegates to a custom factory which is also bound in the injector.
+ */
+final class BoundProviderFactory<T> extends ProviderInternalFactory<T> implements CreationListener {
+
+  private final ProvisionListenerStackCallback<T> provisionCallback;
+  private final InjectorImpl injector;
+  final Key<? extends javax.inject.Provider<? extends T>> providerKey;
+  private InternalFactory<? extends javax.inject.Provider<? extends T>> providerFactory;
+
+  BoundProviderFactory(
+      InjectorImpl injector,
+      Key<? extends javax.inject.Provider<? extends T>> providerKey,
+      Object source,
+      ProvisionListenerStackCallback<T> provisionCallback) {
+    super(source);
+    this.provisionCallback = checkNotNull(provisionCallback, "provisionCallback");
+    this.injector = injector;
+    this.providerKey = providerKey;
+  }
+
+  public void notify(Errors errors) {
+    try {
+      providerFactory = injector.getInternalFactory(providerKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT);
+    } catch (ErrorsException e) {
+      errors.merge(e.getErrors());
+    }
+  }
+
+  public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+      throws ErrorsException {
+    context.pushState(providerKey, source);
+    try {
+      errors = errors.withSource(providerKey);
+      javax.inject.Provider<? extends T> provider = providerFactory.get(errors, context, dependency, true);
+      return circularGet(provider, errors, context, dependency, provisionCallback);
+    } finally {
+      context.popState();
+    }
+  }
+  
+  @Override
+  protected T provision(Provider<? extends T> provider, Errors errors, Dependency<?> dependency,
+      ConstructionContext<T> constructionContext) throws ErrorsException {
+    try {
+      return super.provision(provider, errors, dependency, constructionContext);
+    } catch(RuntimeException userException) {
+      throw errors.errorInProvider(userException).toException();
+    } 
+  }
+
+  @Override public String toString() {
+    return providerKey.toString();
+  }
+}
diff --git a/core/src/com/google/inject/internal/BytecodeGen.java b/core/src/com/google/inject/internal/BytecodeGen.java
new file mode 100644
index 0000000..ed01cd1
--- /dev/null
+++ b/core/src/com/google/inject/internal/BytecodeGen.java
@@ -0,0 +1,334 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.inject.internal.InternalFlags.getCustomClassLoadingOption;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.inject.internal.InternalFlags.CustomClassLoadingOption;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.logging.Logger;
+
+/**
+ * Utility methods for runtime code generation and class loading. We use this stuff for {@link
+ * net.sf.cglib.reflect.FastClass faster reflection}, {@link net.sf.cglib.proxy.Enhancer method
+ * interceptors} and to proxy circular dependencies.
+ *
+ * <p>When loading classes, we need to be careful of:
+ * <ul>
+ *   <li><strong>Memory leaks.</strong> Generated classes need to be garbage collected in long-lived
+ *       applications. Once an injector and any instances it created can be garbage collected, the
+ *       corresponding generated classes should be collectable.
+ *   <li><strong>Visibility.</strong> Containers like <code>OSGi</code> use class loader boundaries
+ *       to enforce modularity at runtime.
+ * </ul>
+ *
+ * <p>For each generated class, there's multiple class loaders involved:
+ * <ul>
+ *    <li><strong>The related class's class loader.</strong> Every generated class services exactly
+ *        one user-supplied class. This class loader must be used to access members with private and
+ *        package visibility.
+ *    <li><strong>Guice's class loader.</strong>
+ *    <li><strong>Our bridge class loader.</strong> This is a child of the user's class loader. It
+ *        selectively delegates to either the user's class loader (for user classes) or the Guice
+ *        class loader (for internal classes that are used by the generated classes). This class
+ *        loader that owns the classes generated by Guice.
+ * </ul>
+ *
+ * @author mcculls@gmail.com (Stuart McCulloch)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public final class BytecodeGen {
+
+  static final Logger logger = Logger.getLogger(BytecodeGen.class.getName());
+
+  static final ClassLoader GUICE_CLASS_LOADER = canonicalize(BytecodeGen.class.getClassLoader());
+
+  // initialization-on-demand...
+  private static class SystemBridgeHolder {
+    static final BridgeClassLoader SYSTEM_BRIDGE = new BridgeClassLoader();
+  }
+
+  /** ie. "com.google.inject.internal" */
+  static final String GUICE_INTERNAL_PACKAGE
+      = BytecodeGen.class.getName().replaceFirst("\\.internal\\..*$", ".internal");
+
+  /*if[AOP]*/
+  /** either "net.sf.cglib", or "com.google.inject.internal.cglib" */
+  static final String CGLIB_PACKAGE
+      = net.sf.cglib.proxy.Enhancer.class.getName().replaceFirst("\\.cglib\\..*$", ".cglib");
+
+  static final net.sf.cglib.core.NamingPolicy FASTCLASS_NAMING_POLICY
+      = new net.sf.cglib.core.DefaultNamingPolicy() {
+    @Override protected String getTag() {
+      return "ByGuice";
+    }
+
+    @Override
+    public String getClassName(String prefix, String source, Object key,
+        net.sf.cglib.core.Predicate names) {
+      // we explicitly set the source here to "FastClass" so that our jarjar renaming
+      // to $FastClass doesn't leak into the class names.  if we did not do this,
+      // classes would end up looking like $$$FastClassByGuice$$, with the extra $
+      // at the front.
+      return super.getClassName(prefix, "FastClass", key, names);
+    }
+  };
+
+  static final net.sf.cglib.core.NamingPolicy ENHANCER_NAMING_POLICY
+      = new net.sf.cglib.core.DefaultNamingPolicy() {
+    @Override
+    protected String getTag() {
+      return "ByGuice";
+    }
+
+    @Override
+    public String getClassName(String prefix, String source, Object key,
+        net.sf.cglib.core.Predicate names) {
+      // we explicitly set the source here to "Enhancer" so that our jarjar renaming
+      // to $Enhancer doesn't leak into the class names.  if we did not do this,
+      // classes would end up looking like $$$EnhancerByGuice$$, with the extra $
+      // at the front.
+      return super.getClassName(prefix, "Enhancer", key, names);
+    }
+  };
+  /*end[AOP]*/
+  /*if[NO_AOP]
+  private static final String CGLIB_PACKAGE = " "; // any string that's illegal in a package name
+  end[NO_AOP]*/
+
+  /**
+   * Weak cache of bridge class loaders that make the Guice implementation
+   * classes visible to various code-generated proxies of client classes.
+   */
+  private static final LoadingCache<ClassLoader, ClassLoader> CLASS_LOADER_CACHE;
+
+  static {
+    CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder().weakKeys().weakValues();
+    if (getCustomClassLoadingOption() == CustomClassLoadingOption.OFF) {
+      builder.maximumSize(0);
+    }
+    CLASS_LOADER_CACHE = builder.build(
+        new CacheLoader<ClassLoader, ClassLoader>() {
+          @Override public ClassLoader load(final ClassLoader typeClassLoader) {
+            logger.fine("Creating a bridge ClassLoader for " + typeClassLoader);
+            return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+              public ClassLoader run() {
+                return new BridgeClassLoader(typeClassLoader);
+              }
+            });
+          }
+        });
+  }
+
+  /**
+   * Attempts to canonicalize null references to the system class loader.
+   * May return null if for some reason the system loader is unavailable.
+   */
+  private static ClassLoader canonicalize(ClassLoader classLoader) {
+    return classLoader != null ? classLoader : SystemBridgeHolder.SYSTEM_BRIDGE.getParent();
+  }
+
+  /**
+   * Returns the class loader to host generated classes for {@code type}.
+   */
+  public static ClassLoader getClassLoader(Class<?> type) {
+    return getClassLoader(type, type.getClassLoader());
+  }
+
+  private static ClassLoader getClassLoader(Class<?> type, ClassLoader delegate) {
+
+    // simple case: do nothing!
+    if (getCustomClassLoadingOption() == CustomClassLoadingOption.OFF) {
+      return delegate;
+    }
+
+    // java.* types can be seen everywhere
+    if (type.getName().startsWith("java.")) {
+      return GUICE_CLASS_LOADER;
+    }
+
+    delegate = canonicalize(delegate);
+
+    // no need for a bridge if using same class loader, or it's already a bridge
+    if (delegate == GUICE_CLASS_LOADER || delegate instanceof BridgeClassLoader) {
+      return delegate;
+    }
+
+    // don't try bridging private types as it won't work
+    if (Visibility.forType(type) == Visibility.PUBLIC) {
+      if (delegate != SystemBridgeHolder.SYSTEM_BRIDGE.getParent()) {
+        // delegate guaranteed to be non-null here
+        return CLASS_LOADER_CACHE.getUnchecked(delegate);
+      }
+      // delegate may or may not be null here
+      return SystemBridgeHolder.SYSTEM_BRIDGE;
+    }
+
+    return delegate; // last-resort: do nothing!
+  }
+
+  /*if[AOP]*/
+  // use fully-qualified names so imports don't need preprocessor statements 
+  public static net.sf.cglib.reflect.FastClass newFastClass(Class<?> type, Visibility visibility) {
+    net.sf.cglib.reflect.FastClass.Generator generator
+        = new net.sf.cglib.reflect.FastClass.Generator();
+    generator.setType(type);
+    if (visibility == Visibility.PUBLIC) {
+      generator.setClassLoader(getClassLoader(type));
+    }
+    generator.setNamingPolicy(FASTCLASS_NAMING_POLICY);
+    logger.fine("Loading " + type + " FastClass with " + generator.getClassLoader());
+    return generator.create();
+  }
+
+  public static net.sf.cglib.proxy.Enhancer newEnhancer(Class<?> type, Visibility visibility) {
+    net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer();
+    enhancer.setSuperclass(type);
+    enhancer.setUseFactory(false);
+    if (visibility == Visibility.PUBLIC) {
+      enhancer.setClassLoader(getClassLoader(type));
+    }
+    enhancer.setNamingPolicy(ENHANCER_NAMING_POLICY);
+    logger.fine("Loading " + type + " Enhancer with " + enhancer.getClassLoader());
+    return enhancer;
+  }
+  /*end[AOP]*/
+
+  /**
+   * The required visibility of a user's class from a Guice-generated class. Visibility of
+   * package-private members depends on the loading classloader: only if two classes were loaded by
+   * the same classloader can they see each other's package-private members. We need to be careful
+   * when choosing which classloader to use for generated classes. We prefer our bridge classloader,
+   * since it's OSGi-safe and doesn't leak permgen space. But often we cannot due to visibility.
+   */
+  public enum Visibility {
+
+    /**
+     * Indicates that Guice-generated classes only need to call and override public members of the
+     * target class. These generated classes may be loaded by our bridge classloader.
+     */
+    PUBLIC {
+      @Override
+      public Visibility and(Visibility that) {
+        return that;
+      }
+    },
+
+    /**
+     * Indicates that Guice-generated classes need to call or override package-private members.
+     * These generated classes must be loaded in the same classloader as the target class. They
+     * won't work with OSGi, and won't get garbage collected until the target class' classloader is
+     * garbage collected.
+     */
+    SAME_PACKAGE {
+      @Override
+      public Visibility and(Visibility that) {
+        return this;
+      }
+    };
+
+    public static Visibility forMember(Member member) {
+      if ((member.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
+        return SAME_PACKAGE;
+      }
+
+      Class[] parameterTypes;
+      if (member instanceof Constructor) {
+        parameterTypes = ((Constructor) member).getParameterTypes();
+      } else {
+        Method method = (Method) member;
+        if (forType(method.getReturnType()) == SAME_PACKAGE) {
+          return SAME_PACKAGE;
+        }
+        parameterTypes = method.getParameterTypes();
+      }
+
+      for (Class<?> type : parameterTypes) {
+        if (forType(type) == SAME_PACKAGE) {
+          return SAME_PACKAGE;
+        }
+      }
+
+      return PUBLIC;
+    }
+
+    public static Visibility forType(Class<?> type) {
+      return (type.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0
+          ? PUBLIC
+          : SAME_PACKAGE;
+    }
+
+    public abstract Visibility and(Visibility that);
+  }
+
+  /**
+   * Loader for Guice-generated classes. For referenced classes, this delegates to either either the
+   * user's classloader (which is the parent of this classloader) or Guice's class loader.
+   */
+  private static class BridgeClassLoader extends ClassLoader {
+
+    BridgeClassLoader() {
+      // use system loader as parent
+    }
+
+    BridgeClassLoader(ClassLoader usersClassLoader) {
+      super(usersClassLoader);
+    }
+
+    @Override protected Class<?> loadClass(String name, boolean resolve)
+        throws ClassNotFoundException {
+
+      if (name.startsWith("sun.reflect")) {
+        // these reflection classes must be loaded from bootstrap class loader
+        return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve);
+      }
+
+      if (name.startsWith(GUICE_INTERNAL_PACKAGE) || name.startsWith(CGLIB_PACKAGE)) {
+        if (null == GUICE_CLASS_LOADER) {
+          // use special system bridge to load classes from bootstrap class loader
+          return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve);
+        }
+        try {
+          Class<?> clazz = GUICE_CLASS_LOADER.loadClass(name);
+          if (resolve) {
+            resolveClass(clazz);
+          }
+          return clazz;
+        } catch (Throwable e) {
+          // fall-back to classic delegation
+        }
+      }
+
+      return classicLoadClass(name, resolve);
+    }
+
+    // make the classic delegating loadClass method visible
+    Class<?> classicLoadClass(String name, boolean resolve)
+      throws ClassNotFoundException {
+      return super.loadClass(name, resolve);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/CircularDependencyProxy.java b/core/src/com/google/inject/internal/CircularDependencyProxy.java
new file mode 100644
index 0000000..fe894a4
--- /dev/null
+++ b/core/src/com/google/inject/internal/CircularDependencyProxy.java
@@ -0,0 +1,24 @@
+/**
+ * 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 com.google.inject.internal;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public interface CircularDependencyProxy {
+  // marker interface
+}
diff --git a/core/src/com/google/inject/internal/ConstantBindingBuilderImpl.java b/core/src/com/google/inject/internal/ConstantBindingBuilderImpl.java
new file mode 100644
index 0000000..8a0c5c6
--- /dev/null
+++ b/core/src/com/google/inject/internal/ConstantBindingBuilderImpl.java
@@ -0,0 +1,131 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.binder.AnnotatedConstantBindingBuilder;
+import com.google.inject.binder.ConstantBindingBuilder;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.InjectionPoint;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+/**
+ * Bind a constant.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public final class ConstantBindingBuilderImpl<T>
+    extends AbstractBindingBuilder<T>
+    implements AnnotatedConstantBindingBuilder, ConstantBindingBuilder {
+
+  @SuppressWarnings("unchecked") // constant bindings start out with T unknown
+  public ConstantBindingBuilderImpl(Binder binder, List<Element> elements, Object source) {
+    super(binder, elements, source, (Key<T>) NULL_KEY);
+  }
+
+  public ConstantBindingBuilder annotatedWith(Class<? extends Annotation> annotationType) {
+    annotatedWithInternal(annotationType);
+    return this;
+  }
+
+  public ConstantBindingBuilder annotatedWith(Annotation annotation) {
+    annotatedWithInternal(annotation);
+    return this;
+  }
+
+  public void to(final String value) {
+    toConstant(String.class, value);
+  }
+
+  public void to(final int value) {
+    toConstant(Integer.class, value);
+  }
+
+  public void to(final long value) {
+    toConstant(Long.class, value);
+  }
+
+  public void to(final boolean value) {
+    toConstant(Boolean.class, value);
+  }
+
+  public void to(final double value) {
+    toConstant(Double.class, value);
+  }
+
+  public void to(final float value) {
+    toConstant(Float.class, value);
+  }
+
+  public void to(final short value) {
+    toConstant(Short.class, value);
+  }
+
+  public void to(final char value) {
+    toConstant(Character.class, value);
+  }
+
+  public void to(final byte value) {
+    toConstant(Byte.class, value);
+  }  
+
+  public void to(final Class<?> value) {
+    toConstant(Class.class, value);
+  }
+
+  public <E extends Enum<E>> void to(final E value) {
+    toConstant(value.getDeclaringClass(), value);
+  }
+
+  private void toConstant(Class<?> type, Object instance) {
+    // this type will define T, so these assignments are safe
+    @SuppressWarnings("unchecked")
+    Class<T> typeAsClassT = (Class<T>) type;
+    @SuppressWarnings("unchecked")
+    T instanceAsT = (T) instance;
+
+    if (keyTypeIsSet()) {
+      binder.addError(CONSTANT_VALUE_ALREADY_SET);
+      return;
+    }
+
+    BindingImpl<T> base = getBinding();
+    Key<T> key;
+    if (base.getKey().getAnnotation() != null) {
+      key = Key.get(typeAsClassT, base.getKey().getAnnotation());
+    } else if (base.getKey().getAnnotationType() != null) {
+      key = Key.get(typeAsClassT, base.getKey().getAnnotationType());
+    } else {
+      key = Key.get(typeAsClassT);
+    }
+
+    if (instanceAsT == null) {
+      binder.addError(BINDING_TO_NULL);
+    }
+
+    setBinding(new InstanceBindingImpl<T>(
+        base.getSource(), key, base.getScoping(), ImmutableSet.<InjectionPoint>of(), instanceAsT));
+  }
+
+  @Override public String toString() {
+    return "ConstantBindingBuilder";
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/ConstantFactory.java b/core/src/com/google/inject/internal/ConstantFactory.java
new file mode 100644
index 0000000..633d5de
--- /dev/null
+++ b/core/src/com/google/inject/internal/ConstantFactory.java
@@ -0,0 +1,43 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.inject.spi.Dependency;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class ConstantFactory<T> implements InternalFactory<T> {
+
+  private final Initializable<T> initializable;
+
+  public ConstantFactory(Initializable<T> initializable) {
+    this.initializable = initializable;
+  }
+
+  public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked)
+      throws ErrorsException {
+    return initializable.get(errors);
+  }
+
+  public String toString() {
+    return Objects.toStringHelper(ConstantFactory.class)
+        .add("value", initializable)
+        .toString();
+  }
+}
diff --git a/core/src/com/google/inject/internal/ConstructionContext.java b/core/src/com/google/inject/internal/ConstructionContext.java
new file mode 100644
index 0000000..ced388f
--- /dev/null
+++ b/core/src/com/google/inject/internal/ConstructionContext.java
@@ -0,0 +1,95 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.inject.internal.InjectorImpl.InjectorOptions;
+
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Context of a dependency construction. Used to manage circular references.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class ConstructionContext<T> {
+
+  T currentReference;
+  boolean constructing;
+
+  List<DelegatingInvocationHandler<T>> invocationHandlers;
+
+  public T getCurrentReference() {
+    return currentReference;
+  }
+
+  public void removeCurrentReference() {
+    this.currentReference = null;
+  }
+
+  public void setCurrentReference(T currentReference) {
+    this.currentReference = currentReference;
+  }
+
+  public boolean isConstructing() {
+    return constructing;
+  }
+
+  public void startConstruction() {
+    this.constructing = true;
+  }
+
+  public void finishConstruction() {
+    this.constructing = false;
+    invocationHandlers = null;
+  }
+
+  public Object createProxy(Errors errors, InjectorOptions injectorOptions,
+      Class<?> expectedType) throws ErrorsException {
+    if (injectorOptions.disableCircularProxies) {
+      throw errors.circularProxiesDisabled(expectedType).toException();
+    }
+    if (!expectedType.isInterface()) {
+      throw errors.cannotSatisfyCircularDependency(expectedType).toException();
+    }
+
+    if (invocationHandlers == null) {
+      invocationHandlers = new ArrayList<DelegatingInvocationHandler<T>>();
+    }
+
+    DelegatingInvocationHandler<T> invocationHandler = new DelegatingInvocationHandler<T>();
+    invocationHandlers.add(invocationHandler);
+
+    // TODO: if I create a proxy which implements all the interfaces of
+    // the implementation type, I'll be able to get away with one proxy
+    // instance (as opposed to one per caller).
+    ClassLoader classLoader = BytecodeGen.getClassLoader(expectedType);
+    return expectedType.cast(Proxy.newProxyInstance(classLoader,
+        new Class[] { expectedType, CircularDependencyProxy.class }, invocationHandler));
+  }
+
+  public void setProxyDelegates(T delegate) {
+    if (invocationHandlers != null) {
+      for (DelegatingInvocationHandler<T> handler : invocationHandlers) {
+        handler.setDelegate(delegate);
+      }
+      // initialization of each handler can happen no more than once
+      invocationHandlers = null;
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ConstructionProxy.java b/core/src/com/google/inject/internal/ConstructionProxy.java
new file mode 100644
index 0000000..6c6f3fc
--- /dev/null
+++ b/core/src/com/google/inject/internal/ConstructionProxy.java
@@ -0,0 +1,57 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.spi.InjectionPoint;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Proxies calls to a {@link java.lang.reflect.Constructor} for a class
+ * {@code T}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+interface ConstructionProxy<T> {
+
+  /**
+   * Constructs an instance of {@code T} for the given arguments.
+   */
+  T newInstance(Object... arguments) throws InvocationTargetException;
+
+  /**
+   * Returns the injection point for this constructor.
+   */
+  InjectionPoint getInjectionPoint();
+
+  /**
+   * Returns the injected constructor. If the injected constructor is synthetic (such as generated
+   * code for method interception), the natural constructor is returned.
+   */
+  Constructor<T> getConstructor();
+
+  /*if[AOP]*/
+  /**
+   * Returns the interceptors applied to each method, in order of invocation.
+   */
+  ImmutableMap<Method, List<org.aopalliance.intercept.MethodInterceptor>> getMethodInterceptors();
+  /*end[AOP]*/
+}
diff --git a/core/src/com/google/inject/internal/ConstructionProxyFactory.java b/core/src/com/google/inject/internal/ConstructionProxyFactory.java
new file mode 100644
index 0000000..0eca0fe
--- /dev/null
+++ b/core/src/com/google/inject/internal/ConstructionProxyFactory.java
@@ -0,0 +1,30 @@
+/**
+ * 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 com.google.inject.internal;
+
+/**
+ * Creates {@link ConstructionProxy} instances.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+interface ConstructionProxyFactory<T> {
+
+  /**
+   * Gets a construction proxy for the given constructor.
+   */
+  ConstructionProxy<T> create() throws ErrorsException;
+}
diff --git a/core/src/com/google/inject/internal/ConstructorBindingImpl.java b/core/src/com/google/inject/internal/ConstructorBindingImpl.java
new file mode 100644
index 0000000..8fb2103
--- /dev/null
+++ b/core/src/com/google/inject/internal/ConstructorBindingImpl.java
@@ -0,0 +1,271 @@
+/*
+ * 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 com.google.inject.internal;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.inject.internal.Annotations.findScopeAnnotation;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.util.Classes;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.ConstructorBinding;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.InjectionPoint;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+final class ConstructorBindingImpl<T> extends BindingImpl<T>
+    implements ConstructorBinding<T>, DelayedInitialize {
+
+  private final Factory<T> factory;
+  private final InjectionPoint constructorInjectionPoint;
+
+  private ConstructorBindingImpl(InjectorImpl injector, Key<T> key, Object source,
+      InternalFactory<? extends T> scopedFactory, Scoping scoping, Factory<T> factory,
+      InjectionPoint constructorInjectionPoint) {
+    super(injector, key, source, scopedFactory, scoping);
+    this.factory = factory;
+    this.constructorInjectionPoint = constructorInjectionPoint;
+  }
+
+  public ConstructorBindingImpl(Key<T> key, Object source, Scoping scoping,
+      InjectionPoint constructorInjectionPoint, Set<InjectionPoint> injectionPoints) {
+    super(source, key, scoping);
+    this.factory = new Factory<T>(false, key);
+    ConstructionProxy<T> constructionProxy
+        = new DefaultConstructionProxyFactory<T>(constructorInjectionPoint).create();
+    this.constructorInjectionPoint = constructorInjectionPoint;
+    factory.constructorInjector = new ConstructorInjector<T>(
+        injectionPoints, constructionProxy, null, null);
+  }
+
+  /**
+   * @param constructorInjector the constructor to use, or {@code null} to use the default.
+   * @param failIfNotLinked true if this ConstructorBindingImpl's InternalFactory should
+   *                             only succeed if retrieved from a linked binding
+   */
+  static <T> ConstructorBindingImpl<T> create(InjectorImpl injector, Key<T> key,
+      InjectionPoint constructorInjector, Object source, Scoping scoping, Errors errors,
+      boolean failIfNotLinked, boolean failIfNotExplicit)
+      throws ErrorsException {
+    int numErrors = errors.size();
+
+    @SuppressWarnings("unchecked") // constructorBinding guarantees type is consistent
+    Class<? super T> rawType = constructorInjector == null
+        ? key.getTypeLiteral().getRawType()
+        : (Class) constructorInjector.getDeclaringType().getRawType();
+
+    // We can't inject abstract classes.
+    if (Modifier.isAbstract(rawType.getModifiers())) {
+      errors.missingImplementation(key);
+    }
+
+    // Error: Inner class.
+    if (Classes.isInnerClass(rawType)) {
+      errors.cannotInjectInnerClass(rawType);
+    }
+
+    errors.throwIfNewErrors(numErrors);
+
+    // Find a constructor annotated @Inject
+    if (constructorInjector == null) {
+      try {
+        constructorInjector = InjectionPoint.forConstructorOf(key.getTypeLiteral());
+        if (failIfNotExplicit && !hasAtInject((Constructor) constructorInjector.getMember())) {
+          errors.atInjectRequired(rawType);
+        }
+      } catch (ConfigurationException e) {
+        throw errors.merge(e.getErrorMessages()).toException();
+      }
+    }
+
+    // if no scope is specified, look for a scoping annotation on the concrete class
+    if (!scoping.isExplicitlyScoped()) {
+      Class<?> annotatedType = constructorInjector.getMember().getDeclaringClass();
+      Class<? extends Annotation> scopeAnnotation = findScopeAnnotation(errors, annotatedType);
+      if (scopeAnnotation != null) {
+        scoping = Scoping.makeInjectable(Scoping.forAnnotation(scopeAnnotation),
+            injector, errors.withSource(rawType));
+      }
+    }
+
+    errors.throwIfNewErrors(numErrors);
+
+    Factory<T> factoryFactory = new Factory<T>(failIfNotLinked, key);
+    InternalFactory<? extends T> scopedFactory
+        = Scoping.scope(key, injector, factoryFactory, source, scoping);
+
+    return new ConstructorBindingImpl<T>(
+        injector, key, source, scopedFactory, scoping, factoryFactory, constructorInjector);
+  }
+
+  /** Returns true if the inject annotation is on the constructor. */
+  private static boolean hasAtInject(Constructor cxtor) {
+    return cxtor.isAnnotationPresent(Inject.class)
+        || cxtor.isAnnotationPresent(javax.inject.Inject.class);
+  }
+
+  @SuppressWarnings("unchecked") // the result type always agrees with the ConstructorInjector type
+  public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
+    factory.constructorInjector =
+        (ConstructorInjector<T>) injector.constructors.get(constructorInjectionPoint, errors);
+    factory.provisionCallback =
+      injector.provisionListenerStore.get(this);
+  }
+
+  /** True if this binding has been initialized and is ready for use. */
+  boolean isInitialized() {
+    return factory.constructorInjector != null;
+  }
+
+  /** Returns an injection point that can be used to clean up the constructor store. */
+  InjectionPoint getInternalConstructor() {
+    if(factory.constructorInjector != null) {
+      return factory.constructorInjector.getConstructionProxy().getInjectionPoint();
+    } else {
+      return constructorInjectionPoint;
+    }
+  }
+
+  /** Returns a set of dependencies that can be iterated over to clean up stray JIT bindings. */
+  Set<Dependency<?>> getInternalDependencies() {
+    ImmutableSet.Builder<InjectionPoint> builder = ImmutableSet.builder();
+    if(factory.constructorInjector == null) {
+      builder.add(constructorInjectionPoint);
+      // If the below throws, it's OK -- we just ignore those dependencies, because no one
+      // could have used them anyway.
+      try {
+        builder.addAll(InjectionPoint.forInstanceMethodsAndFields(constructorInjectionPoint.getDeclaringType()));
+      } catch(ConfigurationException ignored) {}
+    } else {
+      builder.add(getConstructor())
+             .addAll(getInjectableMembers());
+    }
+
+    return Dependency.forInjectionPoints(builder.build());
+  }
+
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
+    checkState(factory.constructorInjector != null, "not initialized");
+    return visitor.visit(this);
+  }
+
+  public InjectionPoint getConstructor() {
+    checkState(factory.constructorInjector != null, "Binding is not ready");
+    return factory.constructorInjector.getConstructionProxy().getInjectionPoint();
+  }
+
+  public Set<InjectionPoint> getInjectableMembers() {
+    checkState(factory.constructorInjector != null, "Binding is not ready");
+    return factory.constructorInjector.getInjectableMembers();
+  }
+
+  /*if[AOP]*/
+  public Map<Method, List<org.aopalliance.intercept.MethodInterceptor>> getMethodInterceptors() {
+    checkState(factory.constructorInjector != null, "Binding is not ready");
+    return factory.constructorInjector.getConstructionProxy().getMethodInterceptors();
+  }
+  /*end[AOP]*/
+
+  public Set<Dependency<?>> getDependencies() {
+    return Dependency.forInjectionPoints(new ImmutableSet.Builder<InjectionPoint>()
+        .add(getConstructor())
+        .addAll(getInjectableMembers())
+        .build());
+  }
+
+  @Override protected BindingImpl<T> withScoping(Scoping scoping) {
+    return new ConstructorBindingImpl<T>(
+        null, getKey(), getSource(), factory, scoping, factory, constructorInjectionPoint);
+  }
+
+  @Override protected BindingImpl<T> withKey(Key<T> key) {
+    return new ConstructorBindingImpl<T>(
+        null, key, getSource(), factory, getScoping(), factory, constructorInjectionPoint);
+  }
+
+  @SuppressWarnings("unchecked") // the raw constructor member and declaring type always agree
+  public void applyTo(Binder binder) {
+    InjectionPoint constructor = getConstructor();
+    getScoping().applyTo(binder.withSource(getSource()).bind(getKey()).toConstructor(
+        (Constructor) getConstructor().getMember(), (TypeLiteral) constructor.getDeclaringType()));
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(ConstructorBinding.class)
+        .add("key", getKey())
+        .add("source", getSource())
+        .add("scope", getScoping())
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if(obj instanceof ConstructorBindingImpl) {
+      ConstructorBindingImpl<?> o = (ConstructorBindingImpl<?>)obj;
+      return getKey().equals(o.getKey())
+        && getScoping().equals(o.getScoping())
+        && Objects.equal(constructorInjectionPoint, o.constructorInjectionPoint);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(getKey(), getScoping(), constructorInjectionPoint);
+  }
+
+  private static class Factory<T> implements InternalFactory<T> {
+    private final boolean failIfNotLinked;
+    private final Key<?> key;
+    private ConstructorInjector<T> constructorInjector;
+    private ProvisionListenerStackCallback<T> provisionCallback;
+
+    Factory(boolean failIfNotLinked, Key<?> key) {
+      this.failIfNotLinked = failIfNotLinked;
+      this.key = key;
+    }
+
+    @SuppressWarnings("unchecked")
+    public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+        throws ErrorsException {
+      checkState(constructorInjector != null, "Constructor not ready");
+
+      if(failIfNotLinked && !linked) {
+        throw errors.jitDisabled(key).toException();
+      }
+
+      // This may not actually be safe because it could return a super type of T (if that's all the
+      // client needs), but it should be OK in practice thanks to the wonders of erasure.
+      return (T) constructorInjector.construct(errors, context,
+          dependency.getKey().getTypeLiteral().getRawType(), provisionCallback);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ConstructorInjector.java b/core/src/com/google/inject/internal/ConstructorInjector.java
new file mode 100644
index 0000000..1ff4be1
--- /dev/null
+++ b/core/src/com/google/inject/internal/ConstructorInjector.java
@@ -0,0 +1,128 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback;
+import com.google.inject.spi.InjectionPoint;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Set;
+
+/**
+ * Creates instances using an injectable constructor. After construction, all injectable fields and
+ * methods are injected.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class ConstructorInjector<T> {
+
+  private final ImmutableSet<InjectionPoint> injectableMembers;
+  private final SingleParameterInjector<?>[] parameterInjectors;
+  private final ConstructionProxy<T> constructionProxy;
+  private final MembersInjectorImpl<T> membersInjector;
+
+  ConstructorInjector(Set<InjectionPoint> injectableMembers,
+      ConstructionProxy<T> constructionProxy,
+      SingleParameterInjector<?>[] parameterInjectors,
+      MembersInjectorImpl<T> membersInjector) {
+    this.injectableMembers = ImmutableSet.copyOf(injectableMembers);
+    this.constructionProxy = constructionProxy;
+    this.parameterInjectors = parameterInjectors;
+    this.membersInjector = membersInjector;
+  }
+
+  public ImmutableSet<InjectionPoint> getInjectableMembers() {
+    return injectableMembers;
+  }
+
+  ConstructionProxy<T> getConstructionProxy() {
+    return constructionProxy;
+  }
+
+  /**
+   * Construct an instance. Returns {@code Object} instead of {@code T} because
+   * it may return a proxy.
+   */
+  Object construct(final Errors errors, final InternalContext context,
+      Class<?> expectedType,
+      ProvisionListenerStackCallback<T> provisionCallback)
+      throws ErrorsException {
+    final ConstructionContext<T> constructionContext = context.getConstructionContext(this);
+
+    // We have a circular reference between constructors. Return a proxy.
+    if (constructionContext.isConstructing()) {
+      // TODO (crazybob): if we can't proxy this object, can we proxy the other object?
+      return constructionContext.createProxy(
+          errors, context.getInjectorOptions(), expectedType);
+    }
+
+    // If we're re-entering this factory while injecting fields or methods,
+    // return the same instance. This prevents infinite loops.
+    T t = constructionContext.getCurrentReference();
+    if (t != null) {
+      return t;
+    }
+
+    constructionContext.startConstruction();
+    try {
+      // Optimization: Don't go through the callback stack if we have no listeners.
+      if (!provisionCallback.hasListeners()) {
+        return provision(errors, context, constructionContext);
+      } else {
+        return provisionCallback.provision(errors, context, new ProvisionCallback<T>() {
+          public T call() throws ErrorsException {
+            return provision(errors, context, constructionContext);
+          }
+        });
+      }
+    } finally {
+      constructionContext.finishConstruction();
+    }
+  }
+
+  /** Provisions a new T. */
+  private T provision(Errors errors, InternalContext context,
+      ConstructionContext<T> constructionContext) throws ErrorsException {
+    try {
+      T t;
+      try {
+        Object[] parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors);
+        t = constructionProxy.newInstance(parameters);
+        constructionContext.setProxyDelegates(t);
+      } finally {
+        constructionContext.finishConstruction();
+      }
+
+      // Store reference. If an injector re-enters this factory, they'll get the same reference.
+      constructionContext.setCurrentReference(t);
+
+      membersInjector.injectMembers(t, errors, context, false);
+      membersInjector.notifyListeners(t, errors);
+
+      return t;
+    } catch (InvocationTargetException userException) {
+      Throwable cause = userException.getCause() != null
+          ? userException.getCause()
+          : userException;
+      throw errors.withSource(constructionProxy.getInjectionPoint())
+          .errorInjectingConstructor(cause).toException();
+    } finally {
+      constructionContext.removeCurrentReference();
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ConstructorInjectorStore.java b/core/src/com/google/inject/internal/ConstructorInjectorStore.java
new file mode 100644
index 0000000..b8e4867
--- /dev/null
+++ b/core/src/com/google/inject/internal/ConstructorInjectorStore.java
@@ -0,0 +1,93 @@
+/**
+ * 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 com.google.inject.internal;
+
+import static com.google.common.collect.Iterables.concat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.spi.InjectionPoint;
+
+/**
+ * Constructor injectors by type.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class ConstructorInjectorStore {
+  private final InjectorImpl injector;
+
+  private final FailableCache<InjectionPoint, ConstructorInjector<?>>  cache
+      = new FailableCache<InjectionPoint, ConstructorInjector<?>> () {
+    @Override
+    protected ConstructorInjector<?> create(InjectionPoint constructorInjector, Errors errors)
+        throws ErrorsException {
+      return createConstructor(constructorInjector, errors);
+    }
+  };
+
+  ConstructorInjectorStore(InjectorImpl injector) {
+    this.injector = injector;
+  }
+
+  /**
+   * Returns a new complete constructor injector with injection listeners registered.
+   */
+  public ConstructorInjector<?> get(InjectionPoint constructorInjector, Errors errors)
+      throws ErrorsException {
+    return cache.get(constructorInjector, errors);
+  }
+  
+  /**
+   * Purges an injection point from the cache. Use this only if the cache is not actually valid and
+   * needs to be purged. (See issue 319 and
+   * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and
+   * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is
+   * necessary.)
+   * 
+   * Returns true if the injector for that point was stored in the cache, false otherwise.
+   */
+  boolean remove(InjectionPoint ip) {
+    return cache.remove(ip);
+  }
+
+  private <T> ConstructorInjector<T> createConstructor(InjectionPoint injectionPoint, Errors errors)
+      throws ErrorsException {
+    int numErrorsBefore = errors.size();
+
+    SingleParameterInjector<?>[] constructorParameterInjectors
+        = injector.getParametersInjectors(injectionPoint.getDependencies(), errors);
+
+    @SuppressWarnings("unchecked") // the injector type agrees with the injection point type
+    MembersInjectorImpl<T> membersInjector = (MembersInjectorImpl<T>) injector.membersInjectorStore
+        .get(injectionPoint.getDeclaringType(), errors);
+
+    /*if[AOP]*/
+    ImmutableList<MethodAspect> injectorAspects = injector.state.getMethodAspects();
+    ImmutableList<MethodAspect> methodAspects = membersInjector.getAddedAspects().isEmpty()
+        ? injectorAspects
+        : ImmutableList.copyOf(concat(injectorAspects, membersInjector.getAddedAspects()));
+    ConstructionProxyFactory<T> factory = new ProxyFactory<T>(injectionPoint, methodAspects);
+    /*end[AOP]*/
+    /*if[NO_AOP]
+    ConstructionProxyFactory<T> factory = new DefaultConstructionProxyFactory<T>(injectionPoint);
+    end[NO_AOP]*/
+
+    errors.throwIfNewErrors(numErrorsBefore);
+
+    return new ConstructorInjector<T>(membersInjector.getInjectionPoints(), factory.create(),
+        constructorParameterInjectors, membersInjector);
+  }
+}
diff --git a/core/src/com/google/inject/internal/ContextualCallable.java b/core/src/com/google/inject/internal/ContextualCallable.java
new file mode 100644
index 0000000..56c0630
--- /dev/null
+++ b/core/src/com/google/inject/internal/ContextualCallable.java
@@ -0,0 +1,24 @@
+/**
+ * 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 com.google.inject.internal;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+interface ContextualCallable<T> {
+  T call(InternalContext context) throws ErrorsException;
+}
diff --git a/core/src/com/google/inject/internal/CreationListener.java b/core/src/com/google/inject/internal/CreationListener.java
new file mode 100644
index 0000000..1779204
--- /dev/null
+++ b/core/src/com/google/inject/internal/CreationListener.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.internal;
+
+/** Something that is notified upon creation. */
+interface CreationListener {
+
+  /** Notifies that creation should happen. */
+  void notify(Errors errors);
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/CycleDetectingLock.java b/core/src/com/google/inject/internal/CycleDetectingLock.java
new file mode 100644
index 0000000..690b151
--- /dev/null
+++ b/core/src/com/google/inject/internal/CycleDetectingLock.java
@@ -0,0 +1,302 @@
+package com.google.inject.internal;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Simplified version of {@link Lock} that is special due to how it handles deadlocks detection.
+ *
+ * <p>Is an inherent part of {@link SingletonScope}, moved into a upper level class due
+ * to its size and complexity.
+ *
+ * @param <ID> Lock identification provided by the client, is returned unmodified to the client
+ *        when lock cycle is detected to identify it. Only toString() needs to be implemented.
+ *        Lock references this object internally,
+ *        for the purposes of Garbage Collection you should not use heavy IDs.
+ *        Lock is referenced by a lock factory as long as it's owned by a thread.
+ *
+ * @see SingletonScope
+ * @see com.google.inject.internal.CycleDetectingLock.CycleDetectingLockFactory
+ *
+ * @author timofeyb (Timothy Basanov)
+ */
+interface CycleDetectingLock<ID> {
+
+  /**
+   * Takes a lock in a blocking fashion in case no potential deadlocks are detected.
+   * If the lock was successfully owned, returns an empty map indicating no detected potential
+   * deadlocks.
+   *
+   * Otherwise, a map indicating threads involved in a potential deadlock are returned.
+   * Map is ordered by dependency cycle and lists locks for each thread that are part of
+   * the loop in order. Returned map is created atomically.
+   *
+   * In case no cycle is detected performance is O(threads creating singletons),
+   * in case cycle is detected performance is O(singleton locks).
+   */
+  ListMultimap<Long, ID> lockOrDetectPotentialLocksCycle();
+
+  /**
+   * Unlocks previously locked lock.
+   */
+  void unlock();
+
+  /**
+   * Wraps locks so they would never cause a deadlock. On each
+   * {@link CycleDetectingLock#lockOrDetectPotentialLocksCycle} we check for dependency cycles
+   * within locks created by the same factory. Either we detect a cycle and return it
+   * or take it atomically.
+   *
+   * <p>Important to note that we do not prevent deadlocks in the client code. As an example:
+   * Thread A takes lock L and creates singleton class CA depending on the singleton class CB.
+   * Meanwhile thread B is creating class CB and is waiting on the lock L. Issue happens
+   * due to client code creating interdependent classes and using locks, where
+   * no guarantees on the creation order from Guice are provided.
+   *
+   * <p>Instances of these locks are not intended to be exposed outside of {@link SingletonScope}.
+   */
+  class CycleDetectingLockFactory<ID> {
+
+    /**
+     * Specifies lock that thread is currently waiting on to own it.
+     * Used only for purposes of locks cycle detection.
+     *
+     * Key: thread id
+     * Value: lock that is being waited on
+     *
+     * Element is added inside {@link #lockOrDetectPotentialLocksCycle()} before {@link Lock#lock}
+     * is called. Element is removed inside {@link #lockOrDetectPotentialLocksCycle()} after
+     * {@link Lock#lock} and synchronously with adding it to {@link #locksOwnedByThread}.
+     *
+     * Same lock can be added for several threads in case all of them are trying to
+     * take it.
+     *
+     * Guarded by {@code this}.
+     */
+    private Map<Long, ReentrantCycleDetectingLock> lockThreadIsWaitingOn = Maps.newHashMap();
+
+    /**
+     * Lists locks that thread owns.
+     * Used only to populate locks in a potential cycle when it is detected.
+     *
+     * Key: thread id
+     * Value: stack of locks that were owned.
+     *
+     * Element is added inside {@link #lockOrDetectPotentialLocksCycle()} after {@link Lock#lock}
+     * is called. Element is removed inside {@link #unlock()} synchronously with
+     * {@link Lock#unlock()} call.
+     *
+     * Same lock can only be present several times for the same thread as locks are
+     * reentrant. Lock can not be owned by several different threads as the same time.
+     *
+     * Guarded by {@code this}.
+     */
+    private final Multimap<Long, ReentrantCycleDetectingLock> locksOwnedByThread =
+        LinkedHashMultimap.create();
+
+    /**
+     * Creates new lock within this factory context. We can guarantee that locks created by
+     * the same factory would not deadlock.
+     *
+     * @param newLockId lock id that would be used to report lock cycles if detected
+     */
+    CycleDetectingLock<ID> create(ID newLockId) {
+      return new ReentrantCycleDetectingLock(newLockId, new ReentrantLock());
+    }
+
+    /** The implementation for {@link CycleDetectingLock}. */
+    class ReentrantCycleDetectingLock implements CycleDetectingLock<ID> {
+
+      /** Underlying lock used for actual waiting when no potential deadlocks are detected. */
+      private final Lock lockImplementation;
+      /** User id for this lock. */
+      private final ID userLockId;
+      /**
+       * Thread id for the thread that owned this lock. Nullable.
+       * Guarded by {@code CycleDetectingLockFactory.this}.
+       */
+      private Long lockOwnerThreadId = null;
+      /**
+       * Number of times that thread owned this lock.
+       * Guarded by {@code CycleDetectingLockFactory.this}.
+       */
+      private int lockReentranceCount = 0;
+
+      ReentrantCycleDetectingLock(ID userLockId, Lock lockImplementation) {
+        this.userLockId = Preconditions.checkNotNull(userLockId, "userLockId");
+        this.lockImplementation = Preconditions.checkNotNull(
+            lockImplementation, "lockImplementation");
+      }
+
+      @Override public ListMultimap<Long, ID> lockOrDetectPotentialLocksCycle() {
+        final long currentThreadId = Thread.currentThread().getId();
+        synchronized (CycleDetectingLockFactory.this) {
+          checkState();
+          ListMultimap<Long, ID> locksInCycle = detectPotentialLocksCycle();
+          if (!locksInCycle.isEmpty()) {
+            // potential deadlock is found, we don't try to take this lock
+            return locksInCycle;
+          }
+
+          lockThreadIsWaitingOn.put(currentThreadId, this);
+        }
+
+        // this may be blocking, but we don't expect it to cause a deadlock
+        lockImplementation.lock();
+
+        synchronized (CycleDetectingLockFactory.this) {
+          // current thread is no longer waiting on this lock
+          lockThreadIsWaitingOn.remove(currentThreadId);
+          checkState();
+
+          // mark it as owned by us
+          lockOwnerThreadId = currentThreadId;
+          lockReentranceCount++;
+          // add this lock to the list of locks owned by a current thread
+          locksOwnedByThread.put(currentThreadId, this);
+        }
+        // no deadlock is found, locking successful
+        return ImmutableListMultimap.of();
+      }
+
+      @Override public void unlock() {
+        final long currentThreadId = Thread.currentThread().getId();
+        synchronized (CycleDetectingLockFactory.this) {
+          checkState();
+          Preconditions.checkState(lockOwnerThreadId != null,
+              "Thread is trying to unlock a lock that is not locked");
+          Preconditions.checkState(lockOwnerThreadId == currentThreadId,
+              "Thread is trying to unlock a lock owned by another thread");
+
+          // releasing underlying lock
+          lockImplementation.unlock();
+
+          // be sure to release the lock synchronously with updating internal state
+          lockReentranceCount--;
+          if (lockReentranceCount == 0) {
+            // we no longer own this lock
+            lockOwnerThreadId = null;
+            Preconditions.checkState(locksOwnedByThread.remove(currentThreadId, this),
+                "Internal error: Can not find this lock in locks owned by a current thread");
+            if (locksOwnedByThread.get(currentThreadId).isEmpty()) {
+              // clearing memory
+              locksOwnedByThread.removeAll(currentThreadId);
+            }
+          }
+        }
+      }
+
+      /** Check consistency of an internal state. */
+      void checkState() throws IllegalStateException {
+        final long currentThreadId = Thread.currentThread().getId();
+        Preconditions.checkState(!lockThreadIsWaitingOn.containsKey(currentThreadId),
+            "Internal error: Thread should not be in a waiting thread on a lock now");
+        if (lockOwnerThreadId != null) {
+          // check state of a locked lock
+          Preconditions.checkState(lockReentranceCount >= 0,
+              "Internal error: Lock ownership and reentrance count internal states do not match");
+          Preconditions.checkState(locksOwnedByThread.get(lockOwnerThreadId).contains(this),
+              "Internal error: Set of locks owned by a current thread and lock "
+                  + "ownership status do not match");
+        } else {
+          // check state of a non locked lock
+          Preconditions.checkState(lockReentranceCount == 0,
+              "Internal error: Reentrance count of a non locked lock is expect to be zero");
+          Preconditions.checkState(!locksOwnedByThread.values().contains(this),
+              "Internal error: Non locked lock should not be owned by any thread");
+        }
+      }
+
+      /**
+       * Algorithm to detect a potential lock cycle.
+       *
+       * For lock's thread owner check which lock is it trying to take.
+       * Repeat recursively. When current thread is found a potential cycle is detected.
+       *
+       * @see CycleDetectingLock#lockOrDetectPotentialLocksCycle()
+       */
+      private ListMultimap<Long, ID> detectPotentialLocksCycle() {
+        final long currentThreadId = Thread.currentThread().getId();
+        if (lockOwnerThreadId == null || lockOwnerThreadId == currentThreadId) {
+          // if nobody owns this lock, lock cycle is impossible
+          // if a current thread owns this lock, we let Guice to handle it
+          return ImmutableListMultimap.of();
+        }
+
+        ListMultimap<Long, ID> potentialLocksCycle = Multimaps.newListMultimap(
+            new LinkedHashMap<Long, Collection<ID>>(),
+            new Supplier<List<ID>>() {
+              @Override
+              public List<ID> get() {
+                return Lists.newArrayList();
+              }
+            });
+        // lock that is a part of a potential locks cycle, starts with current lock
+        ReentrantCycleDetectingLock lockOwnerWaitingOn = this;
+        // try to find a dependency path between lock's owner thread and a current thread
+        while (lockOwnerWaitingOn != null && lockOwnerWaitingOn.lockOwnerThreadId != null) {
+          Long threadOwnerThreadWaits = lockOwnerWaitingOn.lockOwnerThreadId;
+          // in case locks cycle exists lock we're waiting for is part of it
+          potentialLocksCycle.putAll(threadOwnerThreadWaits,
+              getAllLockIdsAfter(threadOwnerThreadWaits, lockOwnerWaitingOn));
+
+          if (threadOwnerThreadWaits == currentThreadId) {
+            // owner thread depends on current thread, cycle detected
+            return potentialLocksCycle;
+          }
+          // going for the next thread we wait on indirectly
+          lockOwnerWaitingOn = lockThreadIsWaitingOn.get(threadOwnerThreadWaits);
+        }
+        // no dependency path from an owner thread to a current thread
+        return ImmutableListMultimap.of();
+      }
+
+      /** Return locks owned by a thread after a lock specified, inclusive. */
+      private List<ID> getAllLockIdsAfter(long threadId, ReentrantCycleDetectingLock lock) {
+        List<ID> ids = Lists.newArrayList();
+        boolean found = false;
+        Collection<ReentrantCycleDetectingLock> ownedLocks = locksOwnedByThread.get(threadId);
+        Preconditions.checkNotNull(ownedLocks,
+            "Internal error: No locks were found taken by a thread");
+        for (ReentrantCycleDetectingLock ownedLock : ownedLocks) {
+          if (ownedLock == lock) {
+            found = true;
+          }
+          if (found) {
+            ids.add(ownedLock.userLockId);
+          }
+        }
+        Preconditions.checkState(found, "Internal error: We can not find locks that "
+            + "created a cycle that we detected");
+        return ids;
+      }
+
+      @Override public String toString() {
+        // copy is made to prevent a data race
+        // no synchronization is used, potentially stale data, should be good enough
+        Long localLockOwnerThreadId = this.lockOwnerThreadId;
+        if (localLockOwnerThreadId != null) {
+          return String.format("CycleDetectingLock[%s][locked by %s]",
+              userLockId, localLockOwnerThreadId);
+        } else {
+          return String.format("CycleDetectingLock[%s][unlocked]", userLockId);
+        }
+      }
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/DefaultConstructionProxyFactory.java b/core/src/com/google/inject/internal/DefaultConstructionProxyFactory.java
new file mode 100644
index 0000000..947b49a
--- /dev/null
+++ b/core/src/com/google/inject/internal/DefaultConstructionProxyFactory.java
@@ -0,0 +1,107 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.internal.BytecodeGen.Visibility;
+import com.google.inject.spi.InjectionPoint;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+/**
+ * Produces construction proxies that invoke the class constructor.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class DefaultConstructionProxyFactory<T> implements ConstructionProxyFactory<T> {
+
+  private final InjectionPoint injectionPoint;
+
+  /**
+   * @param injectionPoint an injection point whose member is a constructor of {@code T}.
+   */
+  DefaultConstructionProxyFactory(InjectionPoint injectionPoint) {
+    this.injectionPoint = injectionPoint;
+  }
+
+  public ConstructionProxy<T> create() {
+    @SuppressWarnings("unchecked") // the injection point is for a constructor of T
+    final Constructor<T> constructor = (Constructor<T>) injectionPoint.getMember();
+
+    // Use FastConstructor if the constructor is public.
+    if (Modifier.isPublic(constructor.getModifiers())) {
+      Class<T> classToConstruct = constructor.getDeclaringClass();
+      /*if[AOP]*/
+      try {
+        final net.sf.cglib.reflect.FastConstructor fastConstructor
+            = BytecodeGen.newFastClass(classToConstruct, Visibility.forMember(constructor))
+                .getConstructor(constructor);
+
+      return new ConstructionProxy<T>() {
+        @SuppressWarnings("unchecked")
+        public T newInstance(Object... arguments) throws InvocationTargetException {
+          return (T) fastConstructor.newInstance(arguments);
+        }
+        public InjectionPoint getInjectionPoint() {
+          return injectionPoint;
+        }
+        public Constructor<T> getConstructor() {
+          return constructor;
+        }
+        public ImmutableMap<Method, List<org.aopalliance.intercept.MethodInterceptor>>
+            getMethodInterceptors() {
+          return ImmutableMap.of();
+        }
+      };
+      } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */}
+      /*end[AOP]*/
+      if (!Modifier.isPublic(classToConstruct.getModifiers())) {
+        constructor.setAccessible(true);
+      }
+    } else {
+      constructor.setAccessible(true);
+    }
+
+    return new ConstructionProxy<T>() {
+      public T newInstance(Object... arguments) throws InvocationTargetException {
+        try {
+          return constructor.newInstance(arguments);
+        } catch (InstantiationException e) {
+          throw new AssertionError(e); // shouldn't happen, we know this is a concrete type
+        } catch (IllegalAccessException e) {
+          throw new AssertionError(e); // a security manager is blocking us, we're hosed
+        }
+      }
+      public InjectionPoint getInjectionPoint() {
+        return injectionPoint;
+      }
+      public Constructor<T> getConstructor() {
+        return constructor;
+      }
+      /*if[AOP]*/
+      public ImmutableMap<Method, List<org.aopalliance.intercept.MethodInterceptor>>
+          getMethodInterceptors() {
+        return ImmutableMap.of();
+      }
+      /*end[AOP]*/
+    };
+  }
+}
diff --git a/core/src/com/google/inject/internal/DeferredLookups.java b/core/src/com/google/inject/internal/DeferredLookups.java
new file mode 100644
index 0000000..049c9a8
--- /dev/null
+++ b/core/src/com/google/inject/internal/DeferredLookups.java
@@ -0,0 +1,63 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.MembersInjectorLookup;
+import com.google.inject.spi.ProviderLookup;
+
+import java.util.List;
+
+/**
+ * Returns providers and members injectors that haven't yet been initialized. As a part of injector
+ * creation it's necessary to {@link #initialize initialize} these lookups.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class DeferredLookups implements Lookups {
+  private final InjectorImpl injector;
+  private final List<Element> lookups = Lists.newArrayList();
+
+  DeferredLookups(InjectorImpl injector) {
+    this.injector = injector;
+  }
+
+  /**
+   * Initialize the specified lookups, either immediately or when the injector is created.
+   */
+  void initialize(Errors errors) {
+    injector.lookups = injector;
+    new LookupProcessor(errors).process(injector, lookups);
+  }
+
+  public <T> Provider<T> getProvider(Key<T> key) {
+    ProviderLookup<T> lookup = new ProviderLookup<T>(key, key);
+    lookups.add(lookup);
+    return lookup.getProvider();
+  }
+
+  public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> type) {
+    MembersInjectorLookup<T> lookup = new MembersInjectorLookup<T>(type, type);
+    lookups.add(lookup);
+    return lookup.getMembersInjector();
+  }
+}
diff --git a/core/src/com/google/inject/internal/DelayedInitialize.java b/core/src/com/google/inject/internal/DelayedInitialize.java
new file mode 100644
index 0000000..82a8463
--- /dev/null
+++ b/core/src/com/google/inject/internal/DelayedInitialize.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.internal;
+
+/**
+ * Something that needs some delayed initialization, typically
+ * a binding or internal factory that needs to be created & put
+ * into the bindings map & then initialized later.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+interface DelayedInitialize {
+  
+  /** Initializes this binding, throwing any errors if necessary. */
+  void initialize(InjectorImpl injector, Errors errors) throws ErrorsException;
+
+}
diff --git a/core/src/com/google/inject/internal/DelegatingInvocationHandler.java b/core/src/com/google/inject/internal/DelegatingInvocationHandler.java
new file mode 100644
index 0000000..32441ff
--- /dev/null
+++ b/core/src/com/google/inject/internal/DelegatingInvocationHandler.java
@@ -0,0 +1,64 @@
+/**
+ * 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 com.google.inject.internal;
+
+
+import com.google.common.base.Preconditions;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+class DelegatingInvocationHandler<T> implements InvocationHandler {
+
+  private volatile boolean initialized;
+
+  private T delegate;
+
+  public Object invoke(Object proxy, Method method, Object[] args)
+      throws Throwable {
+    try {
+      // checking volatile field for synchronization
+      Preconditions.checkState(initialized,
+          "This is a proxy used to support"
+              + " circular references. The object we're"
+              + " proxying is not constructed yet. Please wait until after"
+              + " injection has completed to use this object.");
+      Preconditions.checkNotNull(delegate,
+          "This is a proxy used to support"
+              + " circular references. The object we're "
+              + " proxying is initialized to null."
+              + " No methods can be called.");
+
+      // TODO: method.setAccessible(true); ?
+      // this would fix visibility errors when we proxy a
+      // non-public interface.
+      return method.invoke(delegate, args);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(e);
+    } catch (IllegalArgumentException e) {
+      throw new RuntimeException(e);
+    } catch (InvocationTargetException e) {
+      throw e.getTargetException();
+    }
+  }
+
+  void setDelegate(T delegate) {
+    this.delegate = delegate;
+    initialized = true;
+  }
+}
diff --git a/core/src/com/google/inject/internal/EncounterImpl.java b/core/src/com/google/inject/internal/EncounterImpl.java
new file mode 100644
index 0000000..8aa3e94
--- /dev/null
+++ b/core/src/com/google/inject/internal/EncounterImpl.java
@@ -0,0 +1,144 @@
+/**
+ * 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 com.google.inject.internal;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.InjectionListener;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.TypeEncounter;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class EncounterImpl<T> implements TypeEncounter<T> {
+
+  private final Errors errors;
+  private final Lookups lookups;
+  private List<MembersInjector<? super T>> membersInjectors; // lazy
+  private List<InjectionListener<? super T>> injectionListeners; // lazy
+  /*if[AOP]*/
+  private List<MethodAspect> aspects; // lazy
+  /*end[AOP]*/
+  private boolean valid = true;
+
+  EncounterImpl(Errors errors, Lookups lookups) {
+    this.errors = errors;
+    this.lookups = lookups;
+  }
+
+  void invalidate() {
+    valid = false;
+  }
+
+  /*if[AOP]*/
+  ImmutableList<MethodAspect> getAspects() {
+    return aspects == null
+        ? ImmutableList.<MethodAspect>of()
+        : ImmutableList.copyOf(aspects);
+  }
+
+  public void bindInterceptor(Matcher<? super Method> methodMatcher,
+      org.aopalliance.intercept.MethodInterceptor... interceptors) {
+    checkState(valid, "Encounters may not be used after hear() returns.");
+
+    // make sure the applicable aspects is mutable
+    if (aspects == null) {
+      aspects = Lists.newArrayList();
+    }
+
+    aspects.add(new MethodAspect(Matchers.any(), methodMatcher, interceptors));
+  }
+  /*end[AOP]*/
+
+  ImmutableSet<MembersInjector<? super T>> getMembersInjectors() {
+    return membersInjectors == null
+        ? ImmutableSet.<MembersInjector<? super T>>of()
+        : ImmutableSet.copyOf(membersInjectors);
+  }
+
+  ImmutableSet<InjectionListener<? super T>> getInjectionListeners() {
+    return injectionListeners == null
+        ? ImmutableSet.<InjectionListener<? super T>>of()
+        : ImmutableSet.copyOf(injectionListeners);
+  }
+
+  public void register(MembersInjector<? super T> membersInjector) {
+    checkState(valid, "Encounters may not be used after hear() returns.");
+
+    if (membersInjectors == null) {
+      membersInjectors = Lists.newArrayList();
+    }
+
+    membersInjectors.add(membersInjector);
+  }
+
+  public void register(InjectionListener<? super T> injectionListener) {
+    checkState(valid, "Encounters may not be used after hear() returns.");
+
+    if (injectionListeners == null) {
+      injectionListeners = Lists.newArrayList();
+    }
+
+    injectionListeners.add(injectionListener);
+  }
+
+  public void addError(String message, Object... arguments) {
+    checkState(valid, "Encounters may not be used after hear() returns.");
+    errors.addMessage(message, arguments);
+  }
+
+  public void addError(Throwable t) {
+    checkState(valid, "Encounters may not be used after hear() returns.");
+    errors.errorInUserCode(t, "An exception was caught and reported. Message: %s", t.getMessage());
+  }
+
+  public void addError(Message message) {
+    checkState(valid, "Encounters may not be used after hear() returns.");
+    errors.addMessage(message);
+  }
+
+  public <T> Provider<T> getProvider(Key<T> key) {
+    checkState(valid, "Encounters may not be used after hear() returns.");
+    return lookups.getProvider(key);
+  }
+
+  public <T> Provider<T> getProvider(Class<T> type) {
+    return getProvider(Key.get(type));
+  }
+
+  public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) {
+    checkState(valid, "Encounters may not be used after hear() returns.");
+    return lookups.getMembersInjector(typeLiteral);
+  }
+
+  public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
+    return getMembersInjector(TypeLiteral.get(type));
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/ErrorHandler.java b/core/src/com/google/inject/internal/ErrorHandler.java
new file mode 100644
index 0000000..b448eb7
--- /dev/null
+++ b/core/src/com/google/inject/internal/ErrorHandler.java
@@ -0,0 +1,37 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.inject.spi.Message;
+
+/**
+ * Handles errors in the Injector.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+interface ErrorHandler {
+
+  /**
+   * Handles an error.
+   */
+  void handle(Object source, Errors errors);
+
+  /**
+   * Handles a user-reported error.
+   */
+  void handle(Message message);
+}
diff --git a/core/src/com/google/inject/internal/Errors.java b/core/src/com/google/inject/internal/Errors.java
new file mode 100644
index 0000000..7527e2a
--- /dev/null
+++ b/core/src/com/google/inject/internal/Errors.java
@@ -0,0 +1,842 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Ordering;
+import com.google.common.collect.Sets;
+import com.google.inject.ConfigurationException;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+import com.google.inject.Scope;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.util.Classes;
+import com.google.inject.internal.util.SourceProvider;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.ElementSource;
+import com.google.inject.spi.InjectionListener;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.ScopeBinding;
+import com.google.inject.spi.TypeConverterBinding;
+import com.google.inject.spi.TypeListenerBinding;
+
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Formatter;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A collection of error messages. If this type is passed as a method parameter, the method is
+ * considered to have executed successfully only if new errors were not added to this collection.
+ *
+ * <p>Errors can be chained to provide additional context. To add context, call {@link #withSource}
+ * to create a new Errors instance that contains additional context. All messages added to the
+ * returned instance will contain full context.
+ *
+ * <p>To avoid messages with redundant context, {@link #withSource} should be added sparingly. A
+ * good rule of thumb is to assume a method's caller has already specified enough context to
+ * identify that method. When calling a method that's defined in a different context, call that
+ * method with an errors object that includes its context.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public final class Errors implements Serializable {
+
+  private static final Logger logger = Logger.getLogger(Guice.class.getName());
+
+  private static final Set<Dependency<?>> warnedDependencies =
+      Sets.newSetFromMap(new ConcurrentHashMap<Dependency<?>, Boolean>());
+
+
+  /**
+   * The root errors object. Used to access the list of error messages.
+   */
+  private final Errors root;
+
+  /**
+   * The parent errors object. Used to obtain the chain of source objects.
+   */
+  private final Errors parent;
+
+  /**
+   * The leaf source for errors added here.
+   */
+  private final Object source;
+
+  /**
+   * null unless (root == this) and error messages exist. Never an empty list.
+   */
+  private List<Message> errors; // lazy, use getErrorsForAdd()
+
+  public Errors() {
+    this.root = this;
+    this.parent = null;
+    this.source = SourceProvider.UNKNOWN_SOURCE;
+  }
+
+  public Errors(Object source) {
+    this.root = this;
+    this.parent = null;
+    this.source = source;
+  }
+
+  private Errors(Errors parent, Object source) {
+    this.root = parent.root;
+    this.parent = parent;
+    this.source = source;
+  }
+
+  /**
+   * Returns an instance that uses {@code source} as a reference point for newly added errors.
+   */
+  public Errors withSource(Object source) {
+    return source == this.source || source == SourceProvider.UNKNOWN_SOURCE
+        ? this
+        : new Errors(this, source);
+  }
+
+  /**
+   * We use a fairly generic error message here. The motivation is to share the
+   * same message for both bind time errors:
+   * <pre><code>Guice.createInjector(new AbstractModule() {
+   *   public void configure() {
+   *     bind(Runnable.class);
+   *   }
+   * }</code></pre>
+   * ...and at provide-time errors:
+   * <pre><code>Guice.createInjector().getInstance(Runnable.class);</code></pre>
+   * Otherwise we need to know who's calling when resolving a just-in-time
+   * binding, which makes things unnecessarily complex.
+   */
+  public Errors missingImplementation(Key key) {
+    return addMessage("No implementation for %s was bound.", key);
+  }
+
+  public Errors jitDisabled(Key key) {
+    return addMessage("Explicit bindings are required and %s is not explicitly bound.", key);
+  }
+
+  public Errors jitDisabledInParent(Key<?> key) {
+    return addMessage(
+        "Explicit bindings are required and %s would be bound in a parent injector.%n"
+        + "Please add an explicit binding for it, either in the child or the parent.",
+        key);
+  }
+
+  public Errors atInjectRequired(Class clazz) {
+    return addMessage(
+        "Explicit @Inject annotations are required on constructors,"
+        + " but %s has no constructors annotated with @Inject.",
+        clazz);
+  }
+
+  public Errors converterReturnedNull(String stringValue, Object source,
+      TypeLiteral<?> type, TypeConverterBinding typeConverterBinding) {
+    return addMessage("Received null converting '%s' (bound at %s) to %s%n"
+        + " using %s.",
+        stringValue, convert(source), type, typeConverterBinding);
+  }
+
+  public Errors conversionTypeError(String stringValue, Object source, TypeLiteral<?> type,
+      TypeConverterBinding typeConverterBinding, Object converted) {
+    return addMessage("Type mismatch converting '%s' (bound at %s) to %s%n"
+        + " using %s.%n"
+        + " Converter returned %s.",
+        stringValue, convert(source), type, typeConverterBinding, converted);
+  }
+
+  public Errors conversionError(String stringValue, Object source,
+      TypeLiteral<?> type, TypeConverterBinding typeConverterBinding, RuntimeException cause) {
+    return errorInUserCode(cause, "Error converting '%s' (bound at %s) to %s%n"
+        + " using %s.%n"
+        + " Reason: %s",
+        stringValue, convert(source), type, typeConverterBinding, cause);
+  }
+
+  public Errors ambiguousTypeConversion(String stringValue, Object source, TypeLiteral<?> type,
+      TypeConverterBinding a, TypeConverterBinding b) {
+    return addMessage("Multiple converters can convert '%s' (bound at %s) to %s:%n"
+        + " %s and%n"
+        + " %s.%n"
+        + " Please adjust your type converter configuration to avoid overlapping matches.",
+        stringValue, convert(source), type, a, b);
+  }
+
+  public Errors bindingToProvider() {
+    return addMessage("Binding to Provider is not allowed.");
+  }
+
+  public Errors subtypeNotProvided(Class<? extends Provider<?>> providerType,
+      Class<?> type) {
+    return addMessage("%s doesn't provide instances of %s.", providerType, type);
+  }
+
+  public Errors notASubtype(Class<?> implementationType, Class<?> type) {
+    return addMessage("%s doesn't extend %s.", implementationType, type);
+  }
+
+  public Errors recursiveImplementationType() {
+    return addMessage("@ImplementedBy points to the same class it annotates.");
+  }
+
+  public Errors recursiveProviderType() {
+    return addMessage("@ProvidedBy points to the same class it annotates.");
+  }
+
+  public Errors missingRuntimeRetention(Class<? extends Annotation> annotation) {
+    return addMessage(format("Please annotate %s with @Retention(RUNTIME).", annotation));
+  }
+
+  public Errors missingScopeAnnotation(Class<? extends Annotation> annotation) {
+    return addMessage(format("Please annotate %s with @ScopeAnnotation.", annotation));
+  }
+
+  public Errors optionalConstructor(Constructor constructor) {
+    return addMessage("%s is annotated @Inject(optional=true), "
+        + "but constructors cannot be optional.", constructor);
+  }
+
+  public Errors cannotBindToGuiceType(String simpleName) {
+    return addMessage("Binding to core guice framework type is not allowed: %s.", simpleName);
+  }
+
+  public Errors scopeNotFound(Class<? extends Annotation> scopeAnnotation) {
+    return addMessage("No scope is bound to %s.", scopeAnnotation);
+  }
+
+  public Errors scopeAnnotationOnAbstractType(
+      Class<? extends Annotation> scopeAnnotation, Class<?> type, Object source) {
+    return addMessage("%s is annotated with %s, but scope annotations are not supported "
+        + "for abstract types.%n Bound at %s.", type, scopeAnnotation, convert(source));
+  }
+
+  public Errors misplacedBindingAnnotation(Member member, Annotation bindingAnnotation) {
+    return addMessage("%s is annotated with %s, but binding annotations should be applied "
+        + "to its parameters instead.", member, bindingAnnotation);
+  }
+
+  private static final String CONSTRUCTOR_RULES =
+      "Classes must have either one (and only one) constructor "
+          + "annotated with @Inject or a zero-argument constructor that is not private.";
+
+  public Errors missingConstructor(Class<?> implementation) {
+    return addMessage("Could not find a suitable constructor in %s. " + CONSTRUCTOR_RULES,
+        implementation);
+  }
+
+  public Errors tooManyConstructors(Class<?> implementation) {
+    return addMessage("%s has more than one constructor annotated with @Inject. "
+        + CONSTRUCTOR_RULES, implementation);
+  }
+
+  public Errors constructorNotDefinedByType(Constructor<?> constructor, TypeLiteral<?> type) {
+    return addMessage("%s does not define %s", type, constructor);
+  }
+
+  public Errors duplicateScopes(ScopeBinding existing,
+      Class<? extends Annotation> annotationType, Scope scope) {
+    return addMessage("Scope %s is already bound to %s at %s.%n Cannot bind %s.",
+        existing.getScope(), annotationType, existing.getSource(), scope);
+  }
+
+  public Errors voidProviderMethod() {
+    return addMessage("Provider methods must return a value. Do not return void.");
+  }
+
+  public Errors missingConstantValues() {
+    return addMessage("Missing constant value. Please call to(...).");
+  }
+
+  public Errors cannotInjectInnerClass(Class<?> type) {
+    return addMessage("Injecting into inner classes is not supported.  "
+        + "Please use a 'static' class (top-level or nested) instead of %s.", type);
+  }
+
+  public Errors duplicateBindingAnnotations(Member member,
+      Class<? extends Annotation> a, Class<? extends Annotation> b) {
+    return addMessage("%s has more than one annotation annotated with @BindingAnnotation: "
+        + "%s and %s", member, a, b);
+  }
+
+  public Errors staticInjectionOnInterface(Class<?> clazz) {
+    return addMessage("%s is an interface, but interfaces have no static injection points.", clazz);
+  }
+
+  public Errors cannotInjectFinalField(Field field) {
+    return addMessage("Injected field %s cannot be final.", field);
+  }
+
+  public Errors cannotInjectAbstractMethod(Method method) {
+    return addMessage("Injected method %s cannot be abstract.", method);
+  }
+
+  public Errors cannotInjectNonVoidMethod(Method method) {
+    return addMessage("Injected method %s must return void.", method);
+  }
+
+  public Errors cannotInjectMethodWithTypeParameters(Method method) {
+    return addMessage("Injected method %s cannot declare type parameters of its own.", method);
+  }
+
+  public Errors duplicateScopeAnnotations(
+      Class<? extends Annotation> a, Class<? extends Annotation> b) {
+    return addMessage("More than one scope annotation was found: %s and %s.", a, b);
+  }
+
+  public Errors recursiveBinding() {
+    return addMessage("Binding points to itself.");
+  }
+
+  public Errors bindingAlreadySet(Key<?> key, Object source) {
+    return addMessage("A binding to %s was already configured at %s.", key, convert(source));
+  }
+
+  public Errors jitBindingAlreadySet(Key<?> key) {
+    return addMessage("A just-in-time binding to %s was already configured on a parent injector.", key);
+  }
+
+  public Errors childBindingAlreadySet(Key<?> key, Set<Object> sources) {
+    Formatter allSources = new Formatter();
+    for (Object source : sources) {
+      if (source == null) {
+        allSources.format("%n    (bound by a just-in-time binding)");
+      } else {
+        allSources.format("%n    bound at %s", source);
+      }
+    }
+    Errors errors = addMessage(
+        "Unable to create binding for %s."
+      + " It was already configured on one or more child injectors or private modules"
+      + "%s%n"
+      + "  If it was in a PrivateModule, did you forget to expose the binding?",
+        key, allSources.out());
+    return errors;
+  }
+
+  public Errors errorCheckingDuplicateBinding(Key<?> key, Object source, Throwable t) {
+    return addMessage(
+        "A binding to %s was already configured at %s and an error was thrown "
+      + "while checking duplicate bindings.  Error: %s",
+        key, convert(source), t);
+  }
+
+  public Errors errorInjectingMethod(Throwable cause) {
+    return errorInUserCode(cause, "Error injecting method, %s", cause);
+  }
+
+  public Errors errorNotifyingTypeListener(TypeListenerBinding listener,
+      TypeLiteral<?> type, Throwable cause) {
+    return errorInUserCode(cause,
+        "Error notifying TypeListener %s (bound at %s) of %s.%n"
+        + " Reason: %s",
+        listener.getListener(), convert(listener.getSource()), type, cause);
+  }
+
+  public Errors errorInjectingConstructor(Throwable cause) {
+    return errorInUserCode(cause, "Error injecting constructor, %s", cause);
+  }
+
+  public Errors errorInProvider(RuntimeException runtimeException) {
+    Throwable unwrapped = unwrap(runtimeException);
+    return errorInUserCode(unwrapped, "Error in custom provider, %s", unwrapped);
+  }
+
+  public Errors errorInUserInjector(
+      MembersInjector<?> listener, TypeLiteral<?> type, RuntimeException cause) {
+    return errorInUserCode(cause, "Error injecting %s using %s.%n"
+        + " Reason: %s", type, listener, cause);
+  }
+
+  public Errors errorNotifyingInjectionListener(
+      InjectionListener<?> listener, TypeLiteral<?> type, RuntimeException cause) {
+    return errorInUserCode(cause, "Error notifying InjectionListener %s of %s.%n"
+        + " Reason: %s", listener, type, cause);
+  }
+
+  public Errors exposedButNotBound(Key<?> key) {
+    return addMessage("Could not expose() %s, it must be explicitly bound.", key);
+  }
+
+  public Errors keyNotFullySpecified(TypeLiteral<?> typeLiteral) {
+    return addMessage("%s cannot be used as a key; It is not fully specified.", typeLiteral);
+  }
+
+  public Errors errorEnhancingClass(Class<?> clazz, Throwable cause) {
+    return errorInUserCode(cause, "Unable to method intercept: %s", clazz);
+  }
+
+  public static Collection<Message> getMessagesFromThrowable(Throwable throwable) {
+    if (throwable instanceof ProvisionException) {
+      return ((ProvisionException) throwable).getErrorMessages();
+    } else if (throwable instanceof ConfigurationException) {
+      return ((ConfigurationException) throwable).getErrorMessages();
+    } else if (throwable instanceof CreationException) {
+      return ((CreationException) throwable).getErrorMessages();
+    } else {
+      return ImmutableSet.of();
+    }
+  }
+
+  public Errors errorInUserCode(Throwable cause, String messageFormat, Object... arguments) {
+    Collection<Message> messages = getMessagesFromThrowable(cause);
+
+    if (!messages.isEmpty()) {
+      return merge(messages);
+    } else {
+      return addMessage(cause, messageFormat, arguments);
+    }
+  }
+
+  private Throwable unwrap(RuntimeException runtimeException) {
+   if(runtimeException instanceof Exceptions.UnhandledCheckedUserException) {
+     return runtimeException.getCause();
+   } else {
+     return runtimeException;
+   }
+  }
+
+  public Errors cannotInjectRawProvider() {
+    return addMessage("Cannot inject a Provider that has no type parameter");
+  }
+
+  public Errors cannotInjectRawMembersInjector() {
+    return addMessage("Cannot inject a MembersInjector that has no type parameter");
+  }
+
+  public Errors cannotInjectTypeLiteralOf(Type unsupportedType) {
+    return addMessage("Cannot inject a TypeLiteral of %s", unsupportedType);
+  }
+
+  public Errors cannotInjectRawTypeLiteral() {
+    return addMessage("Cannot inject a TypeLiteral that has no type parameter");
+  }
+
+  public Errors cannotSatisfyCircularDependency(Class<?> expectedType) {
+    return addMessage(
+        "Tried proxying %s to support a circular dependency, but it is not an interface.",
+        expectedType);
+  }
+
+  public Errors circularProxiesDisabled(Class<?> expectedType) {
+    return addMessage(
+        "Tried proxying %s to support a circular dependency, but circular proxies are disabled.",
+        expectedType);
+  }
+
+  public void throwCreationExceptionIfErrorsExist() {
+    if (!hasErrors()) {
+      return;
+    }
+
+    throw new CreationException(getMessages());
+  }
+
+  public void throwConfigurationExceptionIfErrorsExist() {
+    if (!hasErrors()) {
+      return;
+    }
+
+    throw new ConfigurationException(getMessages());
+  }
+
+  public void throwProvisionExceptionIfErrorsExist() {
+    if (!hasErrors()) {
+      return;
+    }
+
+    throw new ProvisionException(getMessages());
+  }
+
+  private Message merge(Message message) {
+    List<Object> sources = Lists.newArrayList();
+    sources.addAll(getSources());
+    sources.addAll(message.getSources());
+    return new Message(sources, message.getMessage(), message.getCause());
+  }
+
+  public Errors merge(Collection<Message> messages) {
+    for (Message message : messages) {
+      addMessage(merge(message));
+    }
+    return this;
+  }
+
+  public Errors merge(Errors moreErrors) {
+    if (moreErrors.root == root || moreErrors.root.errors == null) {
+      return this;
+    }
+
+    merge(moreErrors.root.errors);
+    return this;
+  }
+
+  public List<Object> getSources() {
+    List<Object> sources = Lists.newArrayList();
+    for (Errors e = this; e != null; e = e.parent) {
+      if (e.source != SourceProvider.UNKNOWN_SOURCE) {
+        sources.add(0, e.source);
+      }
+    }
+    return sources;
+  }
+
+  public void throwIfNewErrors(int expectedSize) throws ErrorsException {
+    if (size() == expectedSize) {
+      return;
+    }
+
+    throw toException();
+  }
+
+  public ErrorsException toException() {
+    return new ErrorsException(this);
+  }
+
+  public boolean hasErrors() {
+    return root.errors != null;
+  }
+
+  public Errors addMessage(String messageFormat, Object... arguments) {
+    return addMessage(null, messageFormat, arguments);
+  }
+
+  private Errors addMessage(Throwable cause, String messageFormat, Object... arguments) {
+    String message = format(messageFormat, arguments);
+    addMessage(new Message(getSources(), message, cause));
+    return this;
+  }
+
+  public Errors addMessage(Message message) {
+    if (root.errors == null) {
+      root.errors = Lists.newArrayList();
+    }
+    root.errors.add(message);
+    return this;
+  }
+
+  public static String format(String messageFormat, Object... arguments) {
+    for (int i = 0; i < arguments.length; i++) {
+      arguments[i] = Errors.convert(arguments[i]);
+    }
+    return String.format(messageFormat, arguments);
+  }
+
+  public List<Message> getMessages() {
+    if (root.errors == null) {
+      return ImmutableList.of();
+    }
+
+    return new Ordering<Message>() {
+      @Override
+      public int compare(Message a, Message b) {
+        return a.getSource().compareTo(b.getSource());
+      }
+    }.sortedCopy(root.errors);
+  }
+
+  /** Returns the formatted message for an exception with the specified messages. */
+  public static String format(String heading, Collection<Message> errorMessages) {
+    Formatter fmt = new Formatter().format(heading).format(":%n%n");
+    int index = 1;
+    boolean displayCauses = getOnlyCause(errorMessages) == null;
+
+    for (Message errorMessage : errorMessages) {
+      fmt.format("%s) %s%n", index++, errorMessage.getMessage());
+
+      List<Object> dependencies = errorMessage.getSources();
+      for (int i = dependencies.size() - 1; i >= 0; i--) {
+        Object source = dependencies.get(i);
+        formatSource(fmt, source);
+      }
+
+      Throwable cause = errorMessage.getCause();
+      if (displayCauses && cause != null) {
+        StringWriter writer = new StringWriter();
+        cause.printStackTrace(new PrintWriter(writer));
+        fmt.format("Caused by: %s", writer.getBuffer());
+      }
+
+      fmt.format("%n");
+    }
+
+    if (errorMessages.size() == 1) {
+      fmt.format("1 error");
+    } else {
+      fmt.format("%s errors", errorMessages.size());
+    }
+
+    return fmt.toString();
+  }
+
+  /**
+   * Returns {@code value} if it is non-null allowed to be null. Otherwise a message is added and
+   * an {@code ErrorsException} is thrown.
+   */
+  public <T> T checkForNull(T value, Object source, Dependency<?> dependency)
+      throws ErrorsException {
+    if (value != null || dependency.isNullable() ) {
+      return value;
+    }
+
+    // Hack to allow null parameters to @Provides methods, for backwards compatibility.
+    if (dependency.getInjectionPoint().getMember() instanceof Method) {
+      Method annotated = (Method) dependency.getInjectionPoint().getMember();
+      if (annotated.isAnnotationPresent(Provides.class)) {
+        switch (InternalFlags.getNullableProvidesOption()) {
+          case ERROR:
+            break; // break out & let the below exception happen
+          case IGNORE:
+            return value; // user doesn't care about injecting nulls to non-@Nullables.
+          case WARN:
+            // Warn only once, otherwise we spam logs too much.
+            if (!warnedDependencies.add(dependency)) {
+              return value;
+            }
+            logger.log(Level.WARNING,
+                "Guice injected null into parameter {0} of {1} (a {2}), please mark it @Nullable."
+                    + " Use -Dguice_check_nullable_provides_params=ERROR to turn this into an"
+                    + " error.",
+                new Object[] {
+                    dependency.getParameterIndex(),
+                    convert(dependency.getInjectionPoint().getMember()),
+                    convert(dependency.getKey())});
+            return null; // log & exit.
+        }
+      }
+    }
+
+    int parameterIndex = dependency.getParameterIndex();
+    String parameterName = (parameterIndex != -1)
+        ? "parameter " + parameterIndex + " of "
+        : "";
+    addMessage("null returned by binding at %s%n but %s%s is not @Nullable",
+        source, parameterName, dependency.getInjectionPoint().getMember());
+
+    throw toException();
+  }
+
+  /**
+   * Returns the cause throwable if there is exactly one cause in {@code messages}. If there are
+   * zero or multiple messages with causes, null is returned.
+   */
+  public static Throwable getOnlyCause(Collection<Message> messages) {
+    Throwable onlyCause = null;
+    for (Message message : messages) {
+      Throwable messageCause = message.getCause();
+      if (messageCause == null) {
+        continue;
+      }
+
+      if (onlyCause != null) {
+        return null;
+      }
+
+      onlyCause = messageCause;
+    }
+
+    return onlyCause;
+  }
+
+  public int size() {
+    return root.errors == null ? 0 : root.errors.size();
+  }
+
+  private static abstract class Converter<T> {
+
+    final Class<T> type;
+
+    Converter(Class<T> type) {
+      this.type = type;
+    }
+
+    boolean appliesTo(Object o) {
+      return o != null && type.isAssignableFrom(o.getClass());
+    }
+
+    String convert(Object o) {
+      return toString(type.cast(o));
+    }
+
+    abstract String toString(T t);
+  }
+
+  private static final Collection<Converter<?>> converters = ImmutableList.of(
+      new Converter<Class>(Class.class) {
+        @Override public String toString(Class c) {
+          return c.getName();
+        }
+      },
+      new Converter<Member>(Member.class) {
+        @Override public String toString(Member member) {
+          return Classes.toString(member);
+        }
+      },
+      new Converter<Key>(Key.class) {
+        @Override public String toString(Key key) {
+          if (key.getAnnotationType() != null) {
+            return key.getTypeLiteral() + " annotated with "
+                + (key.getAnnotation() != null ? key.getAnnotation() : key.getAnnotationType());
+          } else {
+            return key.getTypeLiteral().toString();
+          }
+        }
+      });
+
+  public static Object convert(Object o) {
+    ElementSource source = null;
+    if (o instanceof ElementSource) {
+      source = (ElementSource)o;
+      o = source.getDeclaringSource();
+    }
+    return convert(o, source);
+  }
+
+  public static Object convert(Object o, ElementSource source) {
+    for (Converter<?> converter : converters) {
+      if (converter.appliesTo(o)) {
+        return appendModules(converter.convert(o), source);
+      }
+    }
+    return appendModules(o, source);
+  }
+
+  private static Object appendModules(Object source, ElementSource elementSource) {
+    String modules = moduleSourceString(elementSource);
+    if (modules.length() == 0) {
+      return source;
+    } else {
+      return source + modules;
+    }
+  }
+
+  private static String moduleSourceString(ElementSource elementSource) {
+    // if we only have one module (or don't know what they are), then don't bother
+    // reporting it, because the source already is going to report exactly that module.
+    if (elementSource == null) {
+      return "";
+    }
+    List<String> modules = Lists.newArrayList(elementSource.getModuleClassNames());
+    // Insert any original element sources w/ module info into the path.
+    while(elementSource.getOriginalElementSource() != null) {
+      elementSource = elementSource.getOriginalElementSource();
+      modules.addAll(0, elementSource.getModuleClassNames());
+    }
+    if (modules.size() <= 1) {
+      return "";
+    }
+
+    // Ideally we'd do:
+    //    return Joiner.on(" -> ")
+    //        .appendTo(new StringBuilder(" (via modules: "), Lists.reverse(modules))
+    //        .append(")").toString();
+    // ... but for some reason we can't find Lists.reverse, so do it the boring way.
+    StringBuilder builder = new StringBuilder(" (via modules: ");
+    for (int i = modules.size() - 1; i >= 0; i--) {
+      builder.append(modules.get(i));
+      if (i != 0) {
+        builder.append(" -> ");
+      }
+    }
+    builder.append(")");
+    return builder.toString();
+  }
+
+  public static void formatSource(Formatter formatter, Object source) {
+    ElementSource elementSource = null;
+    if (source instanceof ElementSource) {
+      elementSource = (ElementSource)source;
+      source = elementSource.getDeclaringSource();
+    }
+    formatSource(formatter, source, elementSource);
+  }
+
+  public static void formatSource(Formatter formatter, Object source, ElementSource elementSource) {
+    String modules = moduleSourceString(elementSource);
+    if (source instanceof Dependency) {
+      Dependency<?> dependency = (Dependency<?>) source;
+      InjectionPoint injectionPoint = dependency.getInjectionPoint();
+      if (injectionPoint != null) {
+        formatInjectionPoint(formatter, dependency, injectionPoint, elementSource);
+      } else {
+        formatSource(formatter, dependency.getKey(), elementSource);
+      }
+
+    } else if (source instanceof InjectionPoint) {
+      formatInjectionPoint(formatter, null, (InjectionPoint) source, elementSource);
+
+    } else if (source instanceof Class) {
+      formatter.format("  at %s%s%n", StackTraceElements.forType((Class<?>) source), modules);
+
+    } else if (source instanceof Member) {
+      formatter.format("  at %s%s%n", StackTraceElements.forMember((Member) source), modules);
+
+    } else if (source instanceof TypeLiteral) {
+      formatter.format("  while locating %s%s%n", source, modules);
+
+    } else if (source instanceof Key) {
+      Key<?> key = (Key<?>) source;
+      formatter.format("  while locating %s%n", convert(key, elementSource));
+
+    } else if (source instanceof Thread) {
+      formatter.format("  in thread %s%n", source);
+
+    } else {
+      formatter.format("  at %s%s%n", source, modules);
+    }
+  }
+
+  public static void formatInjectionPoint(Formatter formatter, Dependency<?> dependency,
+      InjectionPoint injectionPoint, ElementSource elementSource) {
+    Member member = injectionPoint.getMember();
+    Class<? extends Member> memberType = Classes.memberType(member);
+
+    if (memberType == Field.class) {
+      dependency = injectionPoint.getDependencies().get(0);
+      formatter.format("  while locating %s%n", convert(dependency.getKey(), elementSource));
+      formatter.format("    for field at %s%n", StackTraceElements.forMember(member));
+
+    } else if (dependency != null) {
+      formatter.format("  while locating %s%n", convert(dependency.getKey(), elementSource));
+      formatter.format("    for parameter %s at %s%n",
+          dependency.getParameterIndex(), StackTraceElements.forMember(member));
+
+    } else {
+      formatSource(formatter, injectionPoint.getMember());
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ErrorsException.java b/core/src/com/google/inject/internal/ErrorsException.java
new file mode 100644
index 0000000..57f55c4
--- /dev/null
+++ b/core/src/com/google/inject/internal/ErrorsException.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+/**
+ * Indicates that a result could not be returned while preparing or resolving a binding. The caller
+ * should {@link Errors#merge(Errors) merge} the errors from this exception with their existing
+ * errors.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class ErrorsException extends Exception {
+
+  private final Errors errors;
+
+  public ErrorsException(Errors errors) {
+    this.errors = errors;
+  }
+
+  public Errors getErrors() {
+    return errors;
+  }
+}
diff --git a/core/src/com/google/inject/internal/Exceptions.java b/core/src/com/google/inject/internal/Exceptions.java
new file mode 100644
index 0000000..f9d1e21
--- /dev/null
+++ b/core/src/com/google/inject/internal/Exceptions.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2010 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.inject.internal;
+
+
+/**
+ * Rethrows user-code exceptions in wrapped exceptions so that Errors can target the correct
+ * exception.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+class Exceptions {
+
+  /**
+   * Rethrows the exception (or it's cause, if it has one) directly if possible.
+   * If it was a checked exception, this wraps the exception in a stack trace
+   * with no frames, so that the exception is shown immediately with no frames
+   * above it.
+   */
+  public static RuntimeException rethrowCause(Throwable throwable) {
+    Throwable cause = throwable;
+    if(cause.getCause() != null) {
+      cause = cause.getCause();
+    }
+    return rethrow(cause);
+  }
+  
+  /** Rethrows the exception. */
+  public static RuntimeException rethrow(Throwable throwable) {    
+    if(throwable instanceof RuntimeException) {
+      throw (RuntimeException)throwable;
+    } else if(throwable instanceof Error) {
+      throw (Error)throwable;
+    } else {
+      throw new UnhandledCheckedUserException(throwable);
+    }
+  }
+
+  /**
+   * A marker exception class that we look for in order to unwrap the exception
+   * into the user exception, to provide a cleaner stack trace.
+   */
+  static class UnhandledCheckedUserException extends RuntimeException {
+    public UnhandledCheckedUserException(Throwable cause) {
+      super(cause);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ExposedBindingImpl.java b/core/src/com/google/inject/internal/ExposedBindingImpl.java
new file mode 100644
index 0000000..f17d5a6
--- /dev/null
+++ b/core/src/com/google/inject/internal/ExposedBindingImpl.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.ExposedBinding;
+import com.google.inject.spi.PrivateElements;
+
+import java.util.Set;
+
+public final class ExposedBindingImpl<T> extends BindingImpl<T> implements ExposedBinding<T> {
+
+  private final PrivateElements privateElements;
+
+  public ExposedBindingImpl(InjectorImpl injector, Object source, Key<T> key,
+      InternalFactory<T> factory, PrivateElements privateElements) {
+    super(injector, key, source, factory, Scoping.UNSCOPED);
+    this.privateElements = privateElements;
+  }
+
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
+    return visitor.visit(this);
+  }
+
+  public Set<Dependency<?>> getDependencies() {
+    return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
+  }
+
+  public PrivateElements getPrivateElements() {
+    return privateElements;
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(ExposedBinding.class)
+        .add("key", getKey())
+        .add("source", getSource())
+        .add("privateElements", privateElements)
+        .toString();
+  }
+
+  public void applyTo(Binder binder) {
+    throw new UnsupportedOperationException("This element represents a synthetic binding.");
+  }
+  
+  // Purposely does not override equals/hashcode, because exposed bindings are only equal to
+  // themselves right now -- that is, there cannot be "duplicate" exposed bindings.
+}
diff --git a/core/src/com/google/inject/internal/ExposedKeyFactory.java b/core/src/com/google/inject/internal/ExposedKeyFactory.java
new file mode 100644
index 0000000..52bf7cb
--- /dev/null
+++ b/core/src/com/google/inject/internal/ExposedKeyFactory.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.Key;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.PrivateElements;
+
+/**
+ * This factory exists in a parent injector. When invoked, it retrieves its value from a child
+ * injector.
+ */
+final class ExposedKeyFactory<T> implements InternalFactory<T>, CreationListener {
+  private final Key<T> key;
+  private final PrivateElements privateElements;
+  private BindingImpl<T> delegate;
+
+  ExposedKeyFactory(Key<T> key, PrivateElements privateElements) {
+    this.key = key;
+    this.privateElements = privateElements;
+  }
+
+  public void notify(Errors errors) {
+    InjectorImpl privateInjector = (InjectorImpl) privateElements.getInjector();
+    BindingImpl<T> explicitBinding = privateInjector.state.getExplicitBinding(key);
+
+    // validate that the child injector has its own factory. If the getInternalFactory() returns
+    // this, then that child injector doesn't have a factory (and getExplicitBinding has returned
+    // its parent's binding instead
+    if (explicitBinding.getInternalFactory() == this) {
+      errors.withSource(explicitBinding.getSource()).exposedButNotBound(key);
+      return;
+    }
+
+    this.delegate = explicitBinding;
+  }
+
+  public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+      throws ErrorsException {
+    return delegate.getInternalFactory().get(errors, context, dependency, linked);
+  }
+}
diff --git a/core/src/com/google/inject/internal/ExposureBuilder.java b/core/src/com/google/inject/internal/ExposureBuilder.java
new file mode 100644
index 0000000..3b1c227
--- /dev/null
+++ b/core/src/com/google/inject/internal/ExposureBuilder.java
@@ -0,0 +1,69 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Preconditions;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.binder.AnnotatedElementBuilder;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * For private binder's expose() method.
+ */
+public class ExposureBuilder<T> implements AnnotatedElementBuilder {
+  private final Binder binder;
+  private final Object source;
+  private Key<T> key;
+
+  public ExposureBuilder(Binder binder, Object source, Key<T> key) {
+    this.binder = binder;
+    this.source = source;
+    this.key = key;
+  }
+
+  protected void checkNotAnnotated() {
+    if (key.getAnnotationType() != null) {
+      binder.addError(AbstractBindingBuilder.ANNOTATION_ALREADY_SPECIFIED);
+    }
+  }
+
+  public void annotatedWith(Class<? extends Annotation> annotationType) {
+    Preconditions.checkNotNull(annotationType, "annotationType");
+    checkNotAnnotated();
+    key = Key.get(key.getTypeLiteral(), annotationType);
+  }
+
+  public void annotatedWith(Annotation annotation) {
+    Preconditions.checkNotNull(annotation, "annotation");
+    checkNotAnnotated();
+    key = Key.get(key.getTypeLiteral(), annotation);
+  }
+
+  public Key<?> getKey() {
+    return key;
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  @Override public String toString() {
+    return "AnnotatedElementBuilder";
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/FactoryProxy.java b/core/src/com/google/inject/internal/FactoryProxy.java
new file mode 100644
index 0000000..6416d26
--- /dev/null
+++ b/core/src/com/google/inject/internal/FactoryProxy.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.inject.Key;
+import com.google.inject.internal.InjectorImpl.JitLimitation;
+import com.google.inject.spi.Dependency;
+
+/**
+ * A placeholder which enables us to swap in the real factory once the injector is created.
+ * Used for a linked binding, so that getting the linked binding returns the link's factory.
+ */
+final class FactoryProxy<T> implements InternalFactory<T>, CreationListener {
+
+  private final InjectorImpl injector;
+  private final Key<T> key;
+  private final Key<? extends T> targetKey;
+  private final Object source;
+
+  private InternalFactory<? extends T> targetFactory;
+
+  FactoryProxy(InjectorImpl injector, Key<T> key, Key<? extends T> targetKey, Object source) {
+    this.injector = injector;
+    this.key = key;
+    this.targetKey = targetKey;
+    this.source = source;
+  }
+
+  public void notify(final Errors errors) {
+    try {
+      targetFactory = injector.getInternalFactory(targetKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT);
+    } catch (ErrorsException e) {
+      errors.merge(e.getErrors());
+    }
+  }
+
+  public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+      throws ErrorsException {
+    context.pushState(targetKey, source);
+    try {
+      return targetFactory.get(errors.withSource(targetKey), context, dependency, true);
+    } finally {
+      context.popState();
+    }
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(FactoryProxy.class)
+        .add("key", key)
+        .add("provider", targetFactory)
+        .toString();
+  }
+}
diff --git a/core/src/com/google/inject/internal/FailableCache.java b/core/src/com/google/inject/internal/FailableCache.java
new file mode 100644
index 0000000..acd8be5
--- /dev/null
+++ b/core/src/com/google/inject/internal/FailableCache.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+
+/**
+ * Lazily creates (and caches) values for keys. If creating the value fails (with errors), an
+ * exception is thrown on retrieval.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public abstract class FailableCache<K, V> {
+  
+  private final LoadingCache<K, Object> delegate = CacheBuilder.newBuilder().build(
+      new CacheLoader<K, Object>() {
+        public Object load(K key) {
+          Errors errors = new Errors();
+          V result = null;
+          try {
+            result = FailableCache.this.create(key, errors);
+          } catch (ErrorsException e) {
+            errors.merge(e.getErrors());
+          }
+          return errors.hasErrors() ? errors : result;
+        }
+      });
+
+  protected abstract V create(K key, Errors errors) throws ErrorsException;
+  
+  public V get(K key, Errors errors) throws ErrorsException {
+    Object resultOrError = delegate.getUnchecked(key);
+    if (resultOrError instanceof Errors) {
+      errors.merge((Errors) resultOrError);
+      throw errors.toException();
+    } else {
+      @SuppressWarnings("unchecked") // create returned a non-error result, so this is safe
+      V result = (V) resultOrError;
+      return result;
+    }
+  }
+  
+  boolean remove(K key) {
+    return delegate.asMap().remove(key) != null;
+  }
+}
diff --git a/core/src/com/google/inject/internal/InheritingState.java b/core/src/com/google/inject/internal/InheritingState.java
new file mode 100644
index 0000000..18363f4
--- /dev/null
+++ b/core/src/com/google/inject/internal/InheritingState.java
@@ -0,0 +1,197 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.Scope;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding;
+import com.google.inject.spi.ProvisionListenerBinding;
+import com.google.inject.spi.ScopeBinding;
+import com.google.inject.spi.TypeConverterBinding;
+import com.google.inject.spi.TypeListenerBinding;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class InheritingState implements State {
+
+  private final State parent;
+
+  // Must be a linked hashmap in order to preserve order of bindings in Modules.
+  private final Map<Key<?>, Binding<?>> explicitBindingsMutable = Maps.newLinkedHashMap();
+  private final Map<Key<?>, Binding<?>> explicitBindings
+      = Collections.unmodifiableMap(explicitBindingsMutable);
+  private final Map<Class<? extends Annotation>, ScopeBinding> scopes = Maps.newHashMap();
+  private final List<TypeConverterBinding> converters = Lists.newArrayList();
+  /*if[AOP]*/
+  private final List<MethodAspect> methodAspects = Lists.newArrayList();
+  /*end[AOP]*/
+  private final List<TypeListenerBinding> typeListenerBindings = Lists.newArrayList();
+  private final List<ProvisionListenerBinding> provisionListenerBindings = Lists.newArrayList();
+  private final List<ModuleAnnotatedMethodScannerBinding> scannerBindings = Lists.newArrayList();
+  private final WeakKeySet blacklistedKeys;
+  private final Object lock;
+
+  InheritingState(State parent) {
+    this.parent = checkNotNull(parent, "parent");
+    this.lock = (parent == State.NONE) ? this : parent.lock();
+    this.blacklistedKeys = new WeakKeySet(lock);
+  }
+
+  public State parent() {
+    return parent;
+  }
+
+  @SuppressWarnings("unchecked") // we only put in BindingImpls that match their key types
+  public <T> BindingImpl<T> getExplicitBinding(Key<T> key) {
+    Binding<?> binding = explicitBindings.get(key);
+    return binding != null ? (BindingImpl<T>) binding : parent.getExplicitBinding(key);
+  }
+
+  public Map<Key<?>, Binding<?>> getExplicitBindingsThisLevel() {
+    return explicitBindings;
+  }
+
+  public void putBinding(Key<?> key, BindingImpl<?> binding) {
+    explicitBindingsMutable.put(key, binding);
+  }
+
+  public ScopeBinding getScopeBinding(Class<? extends Annotation> annotationType) {
+    ScopeBinding scopeBinding = scopes.get(annotationType);
+    return scopeBinding != null ? scopeBinding : parent.getScopeBinding(annotationType);
+  }
+
+  public void putScopeBinding(Class<? extends Annotation> annotationType, ScopeBinding scope) {
+    scopes.put(annotationType, scope);
+  }
+
+  public Iterable<TypeConverterBinding> getConvertersThisLevel() {
+    return converters;
+  }
+
+  public void addConverter(TypeConverterBinding typeConverterBinding) {
+    converters.add(typeConverterBinding);
+  }
+
+  public TypeConverterBinding getConverter(
+      String stringValue, TypeLiteral<?> type, Errors errors, Object source) {
+    TypeConverterBinding matchingConverter = null;
+    for (State s = this; s != State.NONE; s = s.parent()) {
+      for (TypeConverterBinding converter : s.getConvertersThisLevel()) {
+        if (converter.getTypeMatcher().matches(type)) {
+          if (matchingConverter != null) {
+            errors.ambiguousTypeConversion(stringValue, source, type, matchingConverter, converter);
+          }
+          matchingConverter = converter;
+        }
+      }
+    }
+    return matchingConverter;
+  }
+
+  /*if[AOP]*/
+  public void addMethodAspect(MethodAspect methodAspect) {
+    methodAspects.add(methodAspect);
+  }
+
+  public ImmutableList<MethodAspect> getMethodAspects() {
+    return new ImmutableList.Builder<MethodAspect>()
+        .addAll(parent.getMethodAspects())
+        .addAll(methodAspects)
+        .build();
+  }
+  /*end[AOP]*/
+
+  public void addTypeListener(TypeListenerBinding listenerBinding) {
+    typeListenerBindings.add(listenerBinding);
+  }
+
+  public List<TypeListenerBinding> getTypeListenerBindings() {
+    List<TypeListenerBinding> parentBindings = parent.getTypeListenerBindings();
+    List<TypeListenerBinding> result =
+        Lists.newArrayListWithCapacity(parentBindings.size() + typeListenerBindings.size());
+    result.addAll(parentBindings);
+    result.addAll(typeListenerBindings);
+    return result;
+  }
+  
+  public void addProvisionListener(ProvisionListenerBinding listenerBinding) {
+    provisionListenerBindings.add(listenerBinding);
+  }
+
+  public List<ProvisionListenerBinding> getProvisionListenerBindings() {
+    List<ProvisionListenerBinding> parentBindings = parent.getProvisionListenerBindings();
+    List<ProvisionListenerBinding> result =
+        Lists.newArrayListWithCapacity(parentBindings.size() + provisionListenerBindings.size());
+    result.addAll(parentBindings);
+    result.addAll(provisionListenerBindings);
+    return result;
+  }
+
+  public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) {
+    scannerBindings.add(scanner);
+  }
+
+  public List<ModuleAnnotatedMethodScannerBinding> getScannerBindings() {
+    List<ModuleAnnotatedMethodScannerBinding> parentBindings = parent.getScannerBindings();
+    List<ModuleAnnotatedMethodScannerBinding> result =
+        Lists.newArrayListWithCapacity(parentBindings.size() + scannerBindings.size());
+    result.addAll(parentBindings);
+    result.addAll(scannerBindings);
+    return result;
+  }
+
+  public void blacklist(Key<?> key, State state, Object source) {
+    parent.blacklist(key, state, source);
+    blacklistedKeys.add(key, state, source);
+  }
+
+  public boolean isBlacklisted(Key<?> key) {
+    return blacklistedKeys.contains(key);
+  }
+  
+  public Set<Object> getSourcesForBlacklistedKey(Key<?> key) {
+    return blacklistedKeys.getSources(key);
+  }
+
+  public Object lock() {
+    return lock;
+  }
+
+  public Map<Class<? extends Annotation>, Scope> getScopes() {
+    ImmutableMap.Builder<Class<? extends Annotation>, Scope> builder = ImmutableMap.builder();
+    for (Map.Entry<Class<? extends Annotation>, ScopeBinding> entry : scopes.entrySet()) {
+      builder.put(entry.getKey(), entry.getValue().getScope());
+    }
+    return builder.build();
+  }
+}
diff --git a/core/src/com/google/inject/internal/Initializable.java b/core/src/com/google/inject/internal/Initializable.java
new file mode 100644
index 0000000..855dd8c
--- /dev/null
+++ b/core/src/com/google/inject/internal/Initializable.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+/**
+ * Holds a reference that requires initialization to be performed before it can be used.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+interface Initializable<T> {
+
+  /**
+   * Ensures the reference is initialized, then returns it.
+   */
+  T get(Errors errors) throws ErrorsException;
+}
diff --git a/core/src/com/google/inject/internal/Initializables.java b/core/src/com/google/inject/internal/Initializables.java
new file mode 100644
index 0000000..82e2868
--- /dev/null
+++ b/core/src/com/google/inject/internal/Initializables.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class Initializables {
+
+  /**
+   * Returns an initializable for an instance that requires no initialization.
+   */
+  static <T> Initializable<T> of(final T instance) {
+    return new Initializable<T>() {
+      public T get(Errors errors) throws ErrorsException {
+        return instance;
+      }
+
+      @Override public String toString() {
+        return String.valueOf(instance);
+      }
+    };
+  }
+}
diff --git a/core/src/com/google/inject/internal/Initializer.java b/core/src/com/google/inject/internal/Initializer.java
new file mode 100644
index 0000000..ff83ea9
--- /dev/null
+++ b/core/src/com/google/inject/internal/Initializer.java
@@ -0,0 +1,189 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.InjectionPoint;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Manages and injects instances at injector-creation time. This is made more complicated by
+ * instances that request other instances while they're being injected. We overcome this by using
+ * {@link Initializable}, which attempts to perform injection before use.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class Initializer {
+  
+  /** the only thread that we'll use to inject members. */
+  private final Thread creatingThread = Thread.currentThread();
+
+  /** zero means everything is injected. */
+  private final CountDownLatch ready = new CountDownLatch(1);
+  
+  /** Maps from instances that need injection to the MembersInjector that will inject them. */
+  private final Map<Object, MembersInjectorImpl<?>> pendingMembersInjectors =
+      Maps.newIdentityHashMap();
+
+  /** Maps instances that need injection to a source that registered them */
+  private final Map<Object, InjectableReference<?>> pendingInjection = Maps.newIdentityHashMap();
+
+  /**
+   * Registers an instance for member injection when that step is performed.
+   *
+   * @param instance an instance that optionally has members to be injected (each annotated with
+   *      @Inject).
+   * @param binding the binding that caused this initializable to be created, if it exists.
+   * @param source the source location that this injection was requested
+   */
+  <T> Initializable<T> requestInjection(InjectorImpl injector, T instance, Binding<T> binding,
+      Object source, Set<InjectionPoint> injectionPoints) {
+    checkNotNull(source);
+    
+    ProvisionListenerStackCallback<T> provisionCallback =
+        binding == null ? null : injector.provisionListenerStore.get(binding);
+
+    // short circuit if the object has no injections or listeners.
+    if (instance == null || (injectionPoints.isEmpty()
+        && !injector.membersInjectorStore.hasTypeListeners()
+        && (provisionCallback == null || !provisionCallback.hasListeners()))) {
+      return Initializables.of(instance);
+    }
+
+    InjectableReference<T> initializable = new InjectableReference<T>(
+        injector, instance, binding == null ? null : binding.getKey(), provisionCallback, source);
+    pendingInjection.put(instance, initializable);
+    return initializable;
+  }
+
+  /**
+   * Prepares member injectors for all injected instances. This prompts Guice to do static analysis
+   * on the injected instances.
+   */
+  void validateOustandingInjections(Errors errors) {
+    for (InjectableReference<?> reference : pendingInjection.values()) {
+      try {
+        pendingMembersInjectors.put(reference.instance, reference.validate(errors));
+      } catch (ErrorsException e) {
+        errors.merge(e.getErrors());
+      }
+    }
+  }
+
+  /**
+   * Performs creation-time injections on all objects that require it. Whenever fulfilling an
+   * injection depends on another object that requires injection, we inject it first. If the two
+   * instances are codependent (directly or transitively), ordering of injection is arbitrary.
+   */
+  void injectAll(final Errors errors) {
+    // loop over a defensive copy since ensureInjected() mutates the set. Unfortunately, that copy
+    // is made complicated by a bug in IBM's JDK, wherein entrySet().toArray(Object[]) doesn't work
+    for (InjectableReference<?> reference : Lists.newArrayList(pendingInjection.values())) {
+      try {
+        reference.get(errors);
+      } catch (ErrorsException e) {
+        errors.merge(e.getErrors());
+      }
+    }
+
+    if (!pendingInjection.isEmpty()) {
+      throw new AssertionError("Failed to satisfy " + pendingInjection);
+    }
+
+    ready.countDown();
+  }
+
+  private class InjectableReference<T> implements Initializable<T> {
+    private final InjectorImpl injector;
+    private final T instance;
+    private final Object source;
+    private final Key<T> key;
+    private final ProvisionListenerStackCallback<T> provisionCallback;
+
+    public InjectableReference(InjectorImpl injector, T instance, Key<T> key,
+        ProvisionListenerStackCallback<T> provisionCallback, Object source) {
+      this.injector = injector;
+      this.key = key; // possibly null!
+      this.provisionCallback = provisionCallback; // possibly null!
+      this.instance = checkNotNull(instance, "instance");
+      this.source = checkNotNull(source, "source");
+    }
+
+    public MembersInjectorImpl<T> validate(Errors errors) throws ErrorsException {
+      @SuppressWarnings("unchecked") // the type of 'T' is a TypeLiteral<T>
+          TypeLiteral<T> type = TypeLiteral.get((Class<T>) instance.getClass());
+      return injector.membersInjectorStore.get(type, errors.withSource(source));
+    }
+
+    /**
+     * Reentrant. If {@code instance} was registered for injection at injector-creation time, this
+     * method will ensure that all its members have been injected before returning.
+     */
+    public T get(Errors errors) throws ErrorsException {
+      if (ready.getCount() == 0) {
+        return instance;
+      }
+
+      // just wait for everything to be injected by another thread
+      if (Thread.currentThread() != creatingThread) {
+        try {
+          ready.await();
+          return instance;
+        } catch (InterruptedException e) {
+          // Give up, since we don't know if our injection is ready
+          throw new RuntimeException(e);
+        }
+      }
+
+      // toInject needs injection, do it right away. we only do this once, even if it fails
+      if (pendingInjection.remove(instance) != null) {
+        // safe because we only insert a members injector for the appropriate instance
+        @SuppressWarnings("unchecked")
+        MembersInjectorImpl<T> membersInjector =
+            (MembersInjectorImpl<T>)pendingMembersInjectors.remove(instance);
+        Preconditions.checkState(membersInjector != null,
+            "No membersInjector available for instance: %s, from key: %s", instance, key);
+        
+        // if in Stage.TOOL, we only want to inject & notify toolable injection points.
+        // (otherwise we'll inject all of them)
+        membersInjector.injectAndNotify(instance,
+            errors.withSource(source),
+            key,
+            provisionCallback,
+            source,
+            injector.options.stage == Stage.TOOL);
+      }
+
+      return instance;
+    }
+
+    @Override public String toString() {
+      return instance.toString();
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/InjectionRequestProcessor.java b/core/src/com/google/inject/internal/InjectionRequestProcessor.java
new file mode 100644
index 0000000..36ad261
--- /dev/null
+++ b/core/src/com/google/inject/internal/InjectionRequestProcessor.java
@@ -0,0 +1,134 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Stage;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.InjectionRequest;
+import com.google.inject.spi.StaticInjectionRequest;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Handles {@code Binder.requestInjection} and {@code Binder.requestStaticInjection} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @author mikeward@google.com (Mike Ward)
+ */
+final class InjectionRequestProcessor extends AbstractProcessor {
+
+  private final List<StaticInjection> staticInjections = Lists.newArrayList();
+  private final Initializer initializer;
+
+  InjectionRequestProcessor(Errors errors, Initializer initializer) {
+    super(errors);
+    this.initializer = initializer;
+  }
+
+  @Override public Boolean visit(StaticInjectionRequest request) {
+    staticInjections.add(new StaticInjection(injector, request));
+    return true;
+  }
+
+  @Override public Boolean visit(InjectionRequest<?> request) {
+    Set<InjectionPoint> injectionPoints;
+    try {
+      injectionPoints = request.getInjectionPoints();
+    } catch (ConfigurationException e) {
+      errors.merge(e.getErrorMessages());
+      injectionPoints = e.getPartialValue();
+    }
+
+    initializer.requestInjection(
+        injector, request.getInstance(), null, request.getSource(), injectionPoints);
+    return true;
+  }
+
+  void validate() {
+    for (StaticInjection staticInjection : staticInjections) {
+      staticInjection.validate();
+    }
+  }
+
+  void injectMembers() {
+    /*
+     * TODO: If you request both a parent class and one of its
+     * subclasses, the parent class's static members will be
+     * injected twice.
+     */
+    for (StaticInjection staticInjection : staticInjections) {
+      staticInjection.injectMembers();
+    }
+  }
+
+  /** A requested static injection. */
+  private class StaticInjection {
+    final InjectorImpl injector;
+    final Object source;
+    final StaticInjectionRequest request;
+    ImmutableList<SingleMemberInjector> memberInjectors;
+
+    public StaticInjection(InjectorImpl injector, StaticInjectionRequest request) {
+      this.injector = injector;
+      this.source = request.getSource();
+      this.request = request;
+    }
+
+    void validate() {
+      Errors errorsForMember = errors.withSource(source);
+      Set<InjectionPoint> injectionPoints;
+      try {
+        injectionPoints = request.getInjectionPoints();
+      } catch (ConfigurationException e) {
+        errorsForMember.merge(e.getErrorMessages());
+        injectionPoints = e.getPartialValue();
+      }
+      if (injectionPoints != null) {
+        memberInjectors = injector.membersInjectorStore.getInjectors(
+            injectionPoints, errorsForMember);
+      } else {
+        memberInjectors = ImmutableList.of();
+      }
+      
+      errors.merge(errorsForMember);
+    }
+
+    void injectMembers() {
+      try {
+        injector.callInContext(new ContextualCallable<Void>() {
+          public Void call(InternalContext context) {
+            for (SingleMemberInjector memberInjector : memberInjectors) {
+              // Run injections if we're not in tool stage (ie, PRODUCTION or DEV),
+              // or if we are in tool stage and the injection point is toolable.
+              if(injector.options.stage != Stage.TOOL || memberInjector.getInjectionPoint().isToolable()) {
+                memberInjector.inject(errors, context, null);
+              }
+            }
+            return null;
+          }
+        });
+      } catch (ErrorsException e) {
+        throw new AssertionError();
+      }
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/InjectorImpl.java b/core/src/com/google/inject/internal/InjectorImpl.java
new file mode 100644
index 0000000..54ce8a3
--- /dev/null
+++ b/core/src/com/google/inject/internal/InjectorImpl.java
@@ -0,0 +1,1120 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.ConfigurationException;
+import com.google.inject.ImplementedBy;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Module;
+import com.google.inject.ProvidedBy;
+import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.Scope;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.util.SourceProvider;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.ConvertedConstantBinding;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ProviderBinding;
+import com.google.inject.spi.TypeConverterBinding;
+import com.google.inject.util.Providers;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Default {@link Injector} implementation.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class InjectorImpl implements Injector, Lookups {
+  public static final TypeLiteral<String> STRING_TYPE = TypeLiteral.get(String.class);
+
+  /** Options that control how the injector behaves. */
+  static class InjectorOptions {
+    final Stage stage;
+    final boolean jitDisabled;
+    final boolean disableCircularProxies;
+    final boolean atInjectRequired;
+    final boolean exactBindingAnnotationsRequired;
+
+    InjectorOptions(Stage stage, boolean jitDisabled, boolean disableCircularProxies,
+        boolean atInjectRequired, boolean exactBindingAnnotationsRequired) {
+      this.stage = stage;
+      this.jitDisabled = jitDisabled;
+      this.disableCircularProxies = disableCircularProxies;
+      this.atInjectRequired = atInjectRequired;
+      this.exactBindingAnnotationsRequired = exactBindingAnnotationsRequired;
+    }
+
+    @Override
+    public String toString() {
+      return Objects.toStringHelper(getClass())
+          .add("stage", stage)
+          .add("jitDisabled", jitDisabled)
+          .add("disableCircularProxies", disableCircularProxies)
+          .add("atInjectRequired", atInjectRequired)
+          .add("exactBindingAnnotationsRequired", exactBindingAnnotationsRequired)
+          .toString();
+    }
+  }
+
+  /** some limitations on what just in time bindings are allowed. */
+  enum JitLimitation {
+    /** does not allow just in time bindings */
+    NO_JIT,
+    /** allows existing just in time bindings, but does not allow new ones */
+    EXISTING_JIT,
+    /** allows existing just in time bindings & allows new ones to be created */
+    NEW_OR_EXISTING_JIT,
+  }
+
+  final State state;
+  final InjectorImpl parent;
+  final BindingsMultimap bindingsMultimap = new BindingsMultimap();
+  final InjectorOptions options;
+
+  /** Just-in-time binding cache. Guarded by state.lock() */
+  final Map<Key<?>, BindingImpl<?>> jitBindings = Maps.newHashMap();
+  /**
+   * Cache of Keys that we were unable to create JIT bindings for, so we don't
+   * keep trying.  Also guarded by state.lock().
+   */
+  final Set<Key<?>> failedJitBindings = Sets.newHashSet();
+
+  Lookups lookups = new DeferredLookups(this);
+
+  InjectorImpl(InjectorImpl parent, State state, InjectorOptions injectorOptions) {
+    this.parent = parent;
+    this.state = state;
+    this.options = injectorOptions;
+
+    if (parent != null) {
+      localContext = parent.localContext;
+    } else {
+      localContext = new ThreadLocal<Object[]>();
+    }
+  }
+
+  /** Indexes bindings by type. */
+  void index() {
+    for (Binding<?> binding : state.getExplicitBindingsThisLevel().values()) {
+      index(binding);
+    }
+  }
+
+  <T> void index(Binding<T> binding) {
+    bindingsMultimap.put(binding.getKey().getTypeLiteral(), binding);
+  }
+
+  public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type) {
+    return bindingsMultimap.getAll(type);
+  }
+
+  /** Returns the binding for {@code key} */
+  public <T> BindingImpl<T> getBinding(Key<T> key) {
+    Errors errors = new Errors(key);
+    try {
+      BindingImpl<T> result = getBindingOrThrow(key, errors, JitLimitation.EXISTING_JIT);
+      errors.throwConfigurationExceptionIfErrorsExist();
+      return result;
+    } catch (ErrorsException e) {
+      throw new ConfigurationException(errors.merge(e.getErrors()).getMessages());
+    }
+  }
+
+  public <T> BindingImpl<T> getExistingBinding(Key<T> key) {
+    // Check explicit bindings, i.e. bindings created by modules.
+    BindingImpl<T> explicitBinding = state.getExplicitBinding(key);
+    if (explicitBinding != null) {
+      return explicitBinding;
+    }
+    synchronized (state.lock()) {
+      // See if any jit bindings have been created for this key.
+      for (InjectorImpl injector = this; injector != null; injector = injector.parent) {
+        @SuppressWarnings("unchecked")
+        BindingImpl<T> jitBinding = (BindingImpl<T>) injector.jitBindings.get(key);
+        if(jitBinding != null) {
+          return jitBinding;
+        }
+      }
+    }
+
+    // If Key is a Provider, we have to see if the type it is providing exists,
+    // and, if so, we have to create the binding for the provider.
+    if(isProvider(key)) {
+      try {
+        // This is safe because isProvider above ensures that T is a Provider<?>
+        @SuppressWarnings({"unchecked", "cast"})
+        Key<?> providedKey = (Key<?>)getProvidedKey((Key)key, new Errors());
+        if(getExistingBinding(providedKey) != null) {
+          return getBinding(key);
+        }
+      } catch(ErrorsException e) {
+        throw new ConfigurationException(e.getErrors().getMessages());
+      }
+    }
+
+    // No existing binding exists.
+    return null;
+  }
+
+  /**
+   * Gets a binding implementation.  First, it check to see if the parent has a binding.  If the
+   * parent has a binding and the binding is scoped, it will use that binding.  Otherwise, this
+   * checks for an explicit binding. If no explicit binding is found, it looks for a just-in-time
+   * binding.
+   */
+  <T> BindingImpl<T> getBindingOrThrow(Key<T> key, Errors errors, JitLimitation jitType)
+      throws ErrorsException {
+    // Check explicit bindings, i.e. bindings created by modules.
+    BindingImpl<T> binding = state.getExplicitBinding(key);
+    if (binding != null) {
+      return binding;
+    }
+
+    // Look for an on-demand binding.
+    return getJustInTimeBinding(key, errors, jitType);
+  }
+
+  public <T> Binding<T> getBinding(Class<T> type) {
+    return getBinding(Key.get(type));
+  }
+
+  public Injector getParent() {
+    return parent;
+  }
+
+  public Injector createChildInjector(Iterable<? extends Module> modules) {
+    return new InternalInjectorCreator()
+        .parentInjector(this)
+        .addModules(modules)
+        .build();
+  }
+
+  public Injector createChildInjector(Module... modules) {
+    return createChildInjector(ImmutableList.copyOf(modules));
+  }
+
+  /**
+   * Returns a just-in-time binding for {@code key}, creating it if necessary.
+   *
+   * @throws ErrorsException if the binding could not be created.
+   */
+  private <T> BindingImpl<T> getJustInTimeBinding(Key<T> key, Errors errors, JitLimitation jitType)
+      throws ErrorsException {
+
+    boolean jitOverride = isProvider(key) || isTypeLiteral(key) || isMembersInjector(key);
+    synchronized (state.lock()) {
+      // first try to find a JIT binding that we've already created
+      for (InjectorImpl injector = this; injector != null; injector = injector.parent) {
+        @SuppressWarnings("unchecked") // we only store bindings that match their key
+        BindingImpl<T> binding = (BindingImpl<T>) injector.jitBindings.get(key);
+
+        if (binding != null) {
+          // If we found a JIT binding and we don't allow them,
+          // fail.  (But allow bindings created through TypeConverters.)
+          if (options.jitDisabled
+              && jitType == JitLimitation.NO_JIT
+              && !jitOverride
+              && !(binding instanceof ConvertedConstantBindingImpl)) {
+            throw errors.jitDisabled(key).toException();
+          } else {
+            return binding;
+          }
+        }
+      }
+
+      // If we previously failed creating this JIT binding and our Errors has
+      // already recorded an error, then just directly throw that error.
+      // We need to do this because it's possible we already cleaned up the
+      // entry in jitBindings (during cleanup), and we may be trying
+      // to create it again (in the case of a recursive JIT binding).
+      // We need both of these guards for different reasons
+      // failedJitBindings.contains: We want to continue processing if we've never
+      //   failed before, so that our initial error message contains
+      //   as much useful information as possible about what errors exist.
+      // errors.hasErrors: If we haven't already failed, then it's OK to
+      //   continue processing, to make sure the ultimate error message
+      //   is the correct one.
+      // See: ImplicitBindingsTest#testRecursiveJitBindingsCleanupCorrectly
+      // for where this guard compes into play.
+      if (failedJitBindings.contains(key) && errors.hasErrors()) {
+        throw errors.toException();
+      }
+      return createJustInTimeBindingRecursive(key, errors, options.jitDisabled, jitType);
+    } // end synchronized(state.lock())
+  }
+
+  /** Returns true if the key type is Provider (but not a subclass of Provider). */
+  private static boolean isProvider(Key<?> key) {
+    return key.getTypeLiteral().getRawType().equals(Provider.class);
+  }
+
+  private static boolean isTypeLiteral(Key<?> key) {
+    return key.getTypeLiteral().getRawType().equals(TypeLiteral.class);
+  }
+
+  private static <T> Key<T> getProvidedKey(Key<Provider<T>> key, Errors errors) throws ErrorsException {
+    Type providerType = key.getTypeLiteral().getType();
+
+    // If the Provider has no type parameter (raw Provider)...
+    if (!(providerType instanceof ParameterizedType)) {
+      throw errors.cannotInjectRawProvider().toException();
+    }
+
+    Type entryType = ((ParameterizedType) providerType).getActualTypeArguments()[0];
+
+    @SuppressWarnings("unchecked") // safe because T came from Key<Provider<T>>
+    Key<T> providedKey = (Key<T>) key.ofType(entryType);
+    return providedKey;
+  }
+
+  /** Returns true if the key type is MembersInjector (but not a subclass of MembersInjector). */
+  private static boolean isMembersInjector(Key<?> key) {
+    return key.getTypeLiteral().getRawType().equals(MembersInjector.class)
+        && key.getAnnotationType() == null;
+  }
+
+  private <T> BindingImpl<MembersInjector<T>> createMembersInjectorBinding(
+      Key<MembersInjector<T>> key, Errors errors) throws ErrorsException {
+    Type membersInjectorType = key.getTypeLiteral().getType();
+    if (!(membersInjectorType instanceof ParameterizedType)) {
+      throw errors.cannotInjectRawMembersInjector().toException();
+    }
+
+    @SuppressWarnings("unchecked") // safe because T came from Key<MembersInjector<T>>
+    TypeLiteral<T> instanceType = (TypeLiteral<T>) TypeLiteral.get(
+        ((ParameterizedType) membersInjectorType).getActualTypeArguments()[0]);
+    MembersInjector<T> membersInjector = membersInjectorStore.get(instanceType, errors);
+
+    InternalFactory<MembersInjector<T>> factory = new ConstantFactory<MembersInjector<T>>(
+        Initializables.of(membersInjector));
+
+
+    return new InstanceBindingImpl<MembersInjector<T>>(this, key, SourceProvider.UNKNOWN_SOURCE,
+        factory, ImmutableSet.<InjectionPoint>of(), membersInjector);
+  }
+
+  /**
+   * Creates a synthetic binding to {@code Provider<T>}, i.e. a binding to the provider from
+   * {@code Binding<T>}.
+   */
+  private <T> BindingImpl<Provider<T>> createProviderBinding(Key<Provider<T>> key, Errors errors)
+      throws ErrorsException {
+    Key<T> providedKey = getProvidedKey(key, errors);
+    BindingImpl<T> delegate = getBindingOrThrow(providedKey, errors, JitLimitation.NO_JIT);
+    return new ProviderBindingImpl<T>(this, key, delegate);
+  }
+
+  private static class ProviderBindingImpl<T> extends BindingImpl<Provider<T>>
+      implements ProviderBinding<Provider<T>>, HasDependencies {
+    final BindingImpl<T> providedBinding;
+
+    ProviderBindingImpl(InjectorImpl injector, Key<Provider<T>> key, Binding<T> providedBinding) {
+      super(injector, key, providedBinding.getSource(), createInternalFactory(providedBinding),
+          Scoping.UNSCOPED);
+      this.providedBinding = (BindingImpl<T>) providedBinding;
+    }
+
+    static <T> InternalFactory<Provider<T>> createInternalFactory(Binding<T> providedBinding) {
+      final Provider<T> provider = providedBinding.getProvider();
+      return new InternalFactory<Provider<T>>() {
+        public Provider<T> get(Errors errors, InternalContext context, Dependency dependency, boolean linked) {
+          return provider;
+        }
+      };
+    }
+
+    public Key<? extends T> getProvidedKey() {
+      return providedBinding.getKey();
+    }
+
+    public <V> V acceptTargetVisitor(BindingTargetVisitor<? super Provider<T>, V> visitor) {
+      return visitor.visit(this);
+    }
+
+    public void applyTo(Binder binder) {
+      throw new UnsupportedOperationException("This element represents a synthetic binding.");
+    }
+
+    @Override public String toString() {
+      return Objects.toStringHelper(ProviderBinding.class)
+          .add("key", getKey())
+          .add("providedKey", getProvidedKey())
+          .toString();
+    }
+
+    public Set<Dependency<?>> getDependencies() {
+      return ImmutableSet.<Dependency<?>>of(Dependency.get(getProvidedKey()));
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if(obj instanceof ProviderBindingImpl) {
+        ProviderBindingImpl<?> o = (ProviderBindingImpl<?>)obj;
+        return getKey().equals(o.getKey())
+          && getScoping().equals(o.getScoping())
+          && Objects.equal(providedBinding, o.providedBinding);
+      } else {
+        return false;
+      }
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hashCode(getKey(), getScoping(), providedBinding);
+    }
+  }
+
+  /**
+   * Converts a constant string binding to the required type.
+   *
+   * @return the binding if it could be resolved, or null if the binding doesn't exist
+   * @throws com.google.inject.internal.ErrorsException if there was an error resolving the binding
+   */
+  private <T> BindingImpl<T> convertConstantStringBinding(Key<T> key, Errors errors)
+      throws ErrorsException {
+    // Find a constant string binding.
+    Key<String> stringKey = key.ofType(STRING_TYPE);
+    BindingImpl<String> stringBinding = state.getExplicitBinding(stringKey);
+    if (stringBinding == null || !stringBinding.isConstant()) {
+      return null;
+    }
+
+    String stringValue = stringBinding.getProvider().get();
+    Object source = stringBinding.getSource();
+
+    // Find a matching type converter.
+    TypeLiteral<T> type = key.getTypeLiteral();
+    TypeConverterBinding typeConverterBinding = state.getConverter(stringValue, type, errors, source);
+
+    if (typeConverterBinding == null) {
+      // No converter can handle the given type.
+      return null;
+    }
+
+    // Try to convert the string. A failed conversion results in an error.
+    try {
+      @SuppressWarnings("unchecked") // This cast is safe because we double check below.
+      T converted = (T) typeConverterBinding.getTypeConverter().convert(stringValue, type);
+
+      if (converted == null) {
+        throw errors.converterReturnedNull(stringValue, source, type, typeConverterBinding)
+            .toException();
+      }
+
+      if (!type.getRawType().isInstance(converted)) {
+        throw errors.conversionTypeError(stringValue, source, type, typeConverterBinding, converted)
+            .toException();
+      }
+
+      return new ConvertedConstantBindingImpl<T>(this, key, converted, stringBinding,
+          typeConverterBinding);
+    } catch (ErrorsException e) {
+      throw e;
+    } catch (RuntimeException e) {
+      throw errors.conversionError(stringValue, source, type, typeConverterBinding, e)
+          .toException();
+    }
+  }
+
+  private static class ConvertedConstantBindingImpl<T>
+      extends BindingImpl<T> implements ConvertedConstantBinding<T> {
+    final T value;
+    final Provider<T> provider;
+    final Binding<String> originalBinding;
+    final TypeConverterBinding typeConverterBinding;
+
+    ConvertedConstantBindingImpl(
+        InjectorImpl injector, Key<T> key, T value, Binding<String> originalBinding,
+        TypeConverterBinding typeConverterBinding) {
+      super(injector, key, originalBinding.getSource(),
+          new ConstantFactory<T>(Initializables.of(value)), Scoping.UNSCOPED);
+      this.value = value;
+      provider = Providers.of(value);
+      this.originalBinding = originalBinding;
+      this.typeConverterBinding = typeConverterBinding;
+    }
+
+    @Override public Provider<T> getProvider() {
+      return provider;
+    }
+
+    public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
+      return visitor.visit(this);
+    }
+
+    public T getValue() {
+      return value;
+    }
+
+    public TypeConverterBinding getTypeConverterBinding() {
+      return typeConverterBinding;
+    }
+
+    public Key<String> getSourceKey() {
+      return originalBinding.getKey();
+    }
+
+    public Set<Dependency<?>> getDependencies() {
+      return ImmutableSet.<Dependency<?>>of(Dependency.get(getSourceKey()));
+    }
+
+    public void applyTo(Binder binder) {
+      throw new UnsupportedOperationException("This element represents a synthetic binding.");
+    }
+
+    @Override public String toString() {
+      return Objects.toStringHelper(ConvertedConstantBinding.class)
+          .add("key", getKey())
+          .add("sourceKey", getSourceKey())
+          .add("value", value)
+          .toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if(obj instanceof ConvertedConstantBindingImpl) {
+        ConvertedConstantBindingImpl<?> o = (ConvertedConstantBindingImpl<?>)obj;
+        return getKey().equals(o.getKey())
+          && getScoping().equals(o.getScoping())
+          && Objects.equal(value, o.value);
+      } else {
+        return false;
+      }
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hashCode(getKey(), getScoping(), value);
+    }
+  }
+
+  <T> void initializeBinding(BindingImpl<T> binding, Errors errors) throws ErrorsException {
+    if (binding instanceof DelayedInitialize) {
+      ((DelayedInitialize) binding).initialize(this, errors);
+    }
+  }
+
+  <T> void initializeJitBinding(BindingImpl<T> binding, Errors errors) throws ErrorsException {
+    // Put the partially constructed binding in the map a little early. This enables us to handle
+    // circular dependencies. Example: FooImpl -> BarImpl -> FooImpl.
+    // Note: We don't need to synchronize on state.lock() during injector creation.
+    if (binding instanceof DelayedInitialize) {
+      Key<T> key = binding.getKey();
+      jitBindings.put(key, binding);
+      boolean successful = false;
+      DelayedInitialize delayed = (DelayedInitialize)binding;
+      try {
+        delayed.initialize(this, errors);
+        successful = true;
+      } finally {
+        if (!successful) {
+          // We do not pass cb.getInternalConstructor as the second parameter
+          // so that cached exceptions while constructing it get stored.
+          // See TypeListenerTest#testTypeListenerThrows
+          removeFailedJitBinding(binding, null);
+          cleanup(binding, new HashSet<Key>());
+        }
+      }
+    }
+  }
+
+  /**
+   * Iterates through the binding's dependencies to clean up any stray bindings that were leftover
+   * from a failed JIT binding. This is required because the bindings are eagerly &
+   * optimistically added to allow circular dependency support, so dependencies may pass where they
+   * should have failed.
+   */
+  private boolean cleanup(BindingImpl<?> binding, Set<Key> encountered) {
+    boolean bindingFailed = false;
+    Set<Dependency<?>> deps = getInternalDependencies(binding);
+    for(Dependency dep : deps) {
+      Key<?> depKey = dep.getKey();
+      InjectionPoint ip = dep.getInjectionPoint();
+      if(encountered.add(depKey)) { // only check if we haven't looked at this key yet
+        BindingImpl depBinding = jitBindings.get(depKey);
+        if(depBinding != null) { // if the binding still exists, validate
+          boolean failed = cleanup(depBinding, encountered); // if children fail, we fail
+          if(depBinding instanceof ConstructorBindingImpl) {
+            ConstructorBindingImpl ctorBinding = (ConstructorBindingImpl)depBinding;
+            ip = ctorBinding.getInternalConstructor();
+            if(!ctorBinding.isInitialized()) {
+              failed = true;
+            }
+          }
+          if(failed) {
+            removeFailedJitBinding(depBinding, ip);
+            bindingFailed = true;
+          }
+        } else if(state.getExplicitBinding(depKey) == null) {
+          // ignore keys if they were explicitly bound, but if neither JIT
+          // nor explicit, it's also invalid & should let parent know.
+          bindingFailed = true;
+        }
+      }
+    }
+    return bindingFailed;
+  }
+
+  /** Cleans up any state that may have been cached when constructing the JIT binding. */
+  private void removeFailedJitBinding(Binding<?> binding, InjectionPoint ip) {
+    failedJitBindings.add(binding.getKey());
+    jitBindings.remove(binding.getKey());
+    membersInjectorStore.remove(binding.getKey().getTypeLiteral());
+    provisionListenerStore.remove(binding);
+    if(ip != null) {
+      constructors.remove(ip);
+    }
+  }
+
+  /** Safely gets the dependencies of possibly not initialized bindings. */
+  @SuppressWarnings("unchecked")
+  private Set<Dependency<?>> getInternalDependencies(BindingImpl<?> binding) {
+    if(binding instanceof ConstructorBindingImpl) {
+      return ((ConstructorBindingImpl)binding).getInternalDependencies();
+    } else if(binding instanceof HasDependencies) {
+      return ((HasDependencies)binding).getDependencies();
+    } else {
+      return ImmutableSet.of();
+    }
+  }
+
+  /**
+   * Creates a binding for an injectable type with the given scope. Looks for a scope on the type if
+   * none is specified.
+   */
+  <T> BindingImpl<T> createUninitializedBinding(Key<T> key, Scoping scoping, Object source,
+      Errors errors, boolean jitBinding) throws ErrorsException {
+    Class<?> rawType = key.getTypeLiteral().getRawType();
+
+    ImplementedBy implementedBy = rawType.getAnnotation(ImplementedBy.class);
+
+    // Don't try to inject arrays or enums annotated with @ImplementedBy.
+    if (rawType.isArray() || (rawType.isEnum() && implementedBy != null)) {
+      throw errors.missingImplementation(key).toException();
+    }
+
+    // Handle TypeLiteral<T> by binding the inner type
+    if (rawType == TypeLiteral.class) {
+      @SuppressWarnings("unchecked") // we have to fudge the inner type as Object
+      BindingImpl<T> binding = (BindingImpl<T>) createTypeLiteralBinding(
+          (Key<TypeLiteral<Object>>) key, errors);
+      return binding;
+    }
+
+    // Handle @ImplementedBy
+    if (implementedBy != null) {
+      Annotations.checkForMisplacedScopeAnnotations(rawType, source, errors);
+      return createImplementedByBinding(key, scoping, implementedBy, errors);
+    }
+
+    // Handle @ProvidedBy.
+    ProvidedBy providedBy = rawType.getAnnotation(ProvidedBy.class);
+    if (providedBy != null) {
+      Annotations.checkForMisplacedScopeAnnotations(rawType, source, errors);
+      return createProvidedByBinding(key, scoping, providedBy, errors);
+    }
+
+
+    return ConstructorBindingImpl.create(this,
+        key,
+        null, /* use default constructor */
+        source,
+        scoping,
+        errors,
+        jitBinding && options.jitDisabled,
+        options.atInjectRequired);
+  }
+
+  /**
+   * Converts a binding for a {@code Key<TypeLiteral<T>>} to the value {@code TypeLiteral<T>}. It's
+   * a bit awkward because we have to pull out the inner type in the type literal.
+   */
+  private <T> BindingImpl<TypeLiteral<T>> createTypeLiteralBinding(
+      Key<TypeLiteral<T>> key, Errors errors) throws ErrorsException {
+    Type typeLiteralType = key.getTypeLiteral().getType();
+    if (!(typeLiteralType instanceof ParameterizedType)) {
+      throw errors.cannotInjectRawTypeLiteral().toException();
+    }
+
+    ParameterizedType parameterizedType = (ParameterizedType) typeLiteralType;
+    Type innerType = parameterizedType.getActualTypeArguments()[0];
+
+    // this is unforunate. We don't support building TypeLiterals for type variable like 'T'. If
+    // this proves problematic, we can probably fix TypeLiteral to support type variables
+    if (!(innerType instanceof Class)
+        && !(innerType instanceof GenericArrayType)
+        && !(innerType instanceof ParameterizedType)) {
+      throw errors.cannotInjectTypeLiteralOf(innerType).toException();
+    }
+
+    @SuppressWarnings("unchecked") // by definition, innerType == T, so this is safe
+    TypeLiteral<T> value = (TypeLiteral<T>) TypeLiteral.get(innerType);
+    InternalFactory<TypeLiteral<T>> factory = new ConstantFactory<TypeLiteral<T>>(
+        Initializables.of(value));
+    return new InstanceBindingImpl<TypeLiteral<T>>(this, key, SourceProvider.UNKNOWN_SOURCE,
+        factory, ImmutableSet.<InjectionPoint>of(), value);
+  }
+
+  /** Creates a binding for a type annotated with @ProvidedBy. */
+  <T> BindingImpl<T> createProvidedByBinding(Key<T> key, Scoping scoping,
+      ProvidedBy providedBy, Errors errors) throws ErrorsException {
+    Class<?> rawType = key.getTypeLiteral().getRawType();
+    Class<? extends Provider<?>> providerType = providedBy.value();
+
+    // Make sure it's not the same type. TODO: Can we check for deeper loops?
+    if (providerType == rawType) {
+      throw errors.recursiveProviderType().toException();
+    }
+
+    // Assume the provider provides an appropriate type. We double check at runtime.
+    @SuppressWarnings("unchecked")
+    Key<? extends Provider<T>> providerKey = (Key<? extends Provider<T>>) Key.get(providerType);
+    ProvidedByInternalFactory<T> internalFactory =
+        new ProvidedByInternalFactory<T>(rawType, providerType, providerKey);
+    Object source = rawType;
+    BindingImpl<T> binding = LinkedProviderBindingImpl.createWithInitializer(
+        this,
+        key,
+        source,
+        Scoping.<T>scope(key, this, internalFactory, source, scoping),
+        scoping,
+        providerKey,
+        internalFactory);
+    internalFactory.setProvisionListenerCallback(provisionListenerStore.get(binding));
+    return binding;
+  }
+
+  /** Creates a binding for a type annotated with @ImplementedBy. */
+  private <T> BindingImpl<T> createImplementedByBinding(Key<T> key, Scoping scoping,
+      ImplementedBy implementedBy, Errors errors)
+      throws ErrorsException {
+    Class<?> rawType = key.getTypeLiteral().getRawType();
+    Class<?> implementationType = implementedBy.value();
+
+    // Make sure it's not the same type. TODO: Can we check for deeper cycles?
+    if (implementationType == rawType) {
+      throw errors.recursiveImplementationType().toException();
+    }
+
+    // Make sure implementationType extends type.
+    if (!rawType.isAssignableFrom(implementationType)) {
+      throw errors.notASubtype(implementationType, rawType).toException();
+    }
+
+    @SuppressWarnings("unchecked") // After the preceding check, this cast is safe.
+    Class<? extends T> subclass = (Class<? extends T>) implementationType;
+
+    // Look up the target binding.
+    final Key<? extends T> targetKey = Key.get(subclass);
+    final BindingImpl<? extends T> targetBinding = getBindingOrThrow(targetKey, errors, JitLimitation.NEW_OR_EXISTING_JIT);
+
+    InternalFactory<T> internalFactory = new InternalFactory<T>() {
+      public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+          throws ErrorsException {
+        context.pushState(targetKey, targetBinding.getSource());
+        try {
+          return targetBinding.getInternalFactory().get(
+              errors.withSource(targetKey), context, dependency, true);
+        } finally {
+          context.popState();
+        }
+      }
+    };
+
+    Object source = rawType;
+    return new LinkedBindingImpl<T>(
+        this,
+        key,
+        source,
+        Scoping.<T>scope(key, this, internalFactory, source, scoping),
+        scoping,
+        targetKey);
+  }
+
+  /**
+   * Attempts to create a just-in-time binding for {@code key} in the root injector, falling back to
+   * other ancestor injectors until this injector is tried.
+   */
+  private <T> BindingImpl<T> createJustInTimeBindingRecursive(Key<T> key, Errors errors,
+      boolean jitDisabled, JitLimitation jitType) throws ErrorsException {
+    // ask the parent to create the JIT binding
+    if (parent != null) {
+      if (jitType == JitLimitation.NEW_OR_EXISTING_JIT
+          && jitDisabled && !parent.options.jitDisabled) {
+        // If the binding would be forbidden here but allowed in a parent, report an error instead
+        throw errors.jitDisabledInParent(key).toException();
+      }
+
+      try {
+        return parent.createJustInTimeBindingRecursive(key, new Errors(), jitDisabled,
+            parent.options.jitDisabled ? JitLimitation.NO_JIT : jitType);
+      } catch (ErrorsException ignored) {
+      }
+    }
+
+    // Retrieve the sources before checking for blacklisting to guard against sources becoming null
+    // due to a full GC happening after calling state.isBlacklisted and
+    // state.getSourcesForBlacklistedKey.
+    // TODO(user): Consolidate these two APIs.
+    Set<Object> sources = state.getSourcesForBlacklistedKey(key);
+    if (state.isBlacklisted(key)) {
+      throw errors.childBindingAlreadySet(key, sources).toException();
+    }
+
+    key = MoreTypes.canonicalizeKey(key); // before storing the key long-term, canonicalize it.
+    BindingImpl<T> binding = createJustInTimeBinding(key, errors, jitDisabled, jitType);
+    state.parent().blacklist(key, state, binding.getSource());
+    jitBindings.put(key, binding);
+    return binding;
+  }
+
+  /**
+   * Returns a new just-in-time binding created by resolving {@code key}. The strategies used to
+   * create just-in-time bindings are:
+   * <ol>
+   *   <li>Internalizing Providers. If the requested binding is for {@code Provider<T>}, we delegate
+   *     to the binding for {@code T}.
+   *   <li>Converting constants.
+   *   <li>ImplementedBy and ProvidedBy annotations. Only for unannotated keys.
+   *   <li>The constructor of the raw type. Only for unannotated keys.
+   * </ol>
+   *
+   * @throws com.google.inject.internal.ErrorsException if the binding cannot be created.
+   */
+  private <T> BindingImpl<T> createJustInTimeBinding(Key<T> key, Errors errors,
+      boolean jitDisabled, JitLimitation jitType) throws ErrorsException {
+    int numErrorsBefore = errors.size();
+
+    // Retrieve the sources before checking for blacklisting to guard against sources becoming null
+    // due to a full GC happening after calling state.isBlacklisted and
+    // state.getSourcesForBlacklistedKey.
+    // TODO(user): Consolidate these two APIs.
+    Set<Object> sources = state.getSourcesForBlacklistedKey(key);
+    if (state.isBlacklisted(key)) {
+      throw errors.childBindingAlreadySet(key, sources).toException();
+    }
+
+    // Handle cases where T is a Provider<?>.
+    if (isProvider(key)) {
+      // These casts are safe. We know T extends Provider<X> and that given Key<Provider<X>>,
+      // createProviderBinding() will return BindingImpl<Provider<X>>.
+      @SuppressWarnings({"unchecked", "cast"})
+      BindingImpl<T> binding = (BindingImpl<T>) createProviderBinding((Key) key, errors);
+      return binding;
+    }
+
+    // Handle cases where T is a MembersInjector<?>
+    if (isMembersInjector(key)) {
+      // These casts are safe. T extends MembersInjector<X> and that given Key<MembersInjector<X>>,
+      // createMembersInjectorBinding() will return BindingImpl<MembersInjector<X>>.
+      @SuppressWarnings({"unchecked", "cast"})
+      BindingImpl<T> binding = (BindingImpl<T>) createMembersInjectorBinding((Key) key, errors);
+      return binding;
+    }
+
+    // Try to convert a constant string binding to the requested type.
+    BindingImpl<T> convertedBinding = convertConstantStringBinding(key, errors);
+    if (convertedBinding != null) {
+      return convertedBinding;
+    }
+
+    if (!isTypeLiteral(key)
+        && jitDisabled
+        && jitType != JitLimitation.NEW_OR_EXISTING_JIT) {
+      throw errors.jitDisabled(key).toException();
+    }
+
+    // If the key has an annotation...
+    if (key.getAnnotationType() != null) {
+      // Look for a binding without annotation attributes or return null.
+      if (key.hasAttributes() && !options.exactBindingAnnotationsRequired) {
+        try {
+          Errors ignored = new Errors();
+          return getBindingOrThrow(key.withoutAttributes(), ignored, JitLimitation.NO_JIT);
+        } catch (ErrorsException ignored) {
+          // throw with a more appropriate message below
+        }
+      }
+      throw errors.missingImplementation(key).toException();
+    }
+
+    Object source = key.getTypeLiteral().getRawType();
+    BindingImpl<T> binding = createUninitializedBinding(key, Scoping.UNSCOPED, source, errors, true);
+    errors.throwIfNewErrors(numErrorsBefore);
+    initializeJitBinding(binding, errors);
+    return binding;
+  }
+
+  <T> InternalFactory<? extends T> getInternalFactory(Key<T> key, Errors errors, JitLimitation jitType)
+      throws ErrorsException {
+    return getBindingOrThrow(key, errors, jitType).getInternalFactory();
+  }
+
+  public Map<Key<?>, Binding<?>> getBindings() {
+    return state.getExplicitBindingsThisLevel();
+  }
+
+  public Map<Key<?>, Binding<?>> getAllBindings() {
+    synchronized (state.lock()) {
+      return new ImmutableMap.Builder<Key<?>, Binding<?>>()
+          .putAll(state.getExplicitBindingsThisLevel())
+          .putAll(jitBindings)
+          .build();
+    }
+  }
+
+  public Map<Class<? extends Annotation>, Scope> getScopeBindings() {
+    return ImmutableMap.copyOf(state.getScopes());
+  }
+
+  public Set<TypeConverterBinding> getTypeConverterBindings() {
+    return ImmutableSet.copyOf(state.getConvertersThisLevel());
+  }
+
+  private static class BindingsMultimap {
+    final Map<TypeLiteral<?>, List<Binding<?>>> multimap = Maps.newHashMap();
+
+    <T> void put(TypeLiteral<T> type, Binding<T> binding) {
+      List<Binding<?>> bindingsForType = multimap.get(type);
+      if (bindingsForType == null) {
+        bindingsForType = Lists.newArrayList();
+        multimap.put(type, bindingsForType);
+      }
+      bindingsForType.add(binding);
+    }
+
+
+    @SuppressWarnings("unchecked") // safe because we only put matching entries into the map
+    <T> List<Binding<T>> getAll(TypeLiteral<T> type) {
+      List<Binding<?>> bindings = multimap.get(type);
+      return bindings != null
+          ? Collections.<Binding<T>>unmodifiableList((List) multimap.get(type))
+          : ImmutableList.<Binding<T>>of();
+    }
+  }
+
+  /**
+   * Returns parameter injectors, or {@code null} if there are no parameters.
+   */
+  SingleParameterInjector<?>[] getParametersInjectors(
+      List<Dependency<?>> parameters, Errors errors) throws ErrorsException {
+    if (parameters.isEmpty()) {
+      return null;
+    }
+
+    int numErrorsBefore = errors.size();
+    SingleParameterInjector<?>[] result = new SingleParameterInjector<?>[parameters.size()];
+    int i = 0;
+    for (Dependency<?> parameter : parameters) {
+      try {
+        result[i++] = createParameterInjector(parameter, errors.withSource(parameter));
+      } catch (ErrorsException rethrownBelow) {
+        // rethrown below
+      }
+    }
+
+    errors.throwIfNewErrors(numErrorsBefore);
+    return result;
+  }
+
+  <T> SingleParameterInjector<T> createParameterInjector(final Dependency<T> dependency,
+      final Errors errors) throws ErrorsException {
+    BindingImpl<? extends T> binding = getBindingOrThrow(dependency.getKey(), errors, JitLimitation.NO_JIT);
+    return new SingleParameterInjector<T>(dependency, binding);
+  }
+
+  /** Invokes a method. */
+  interface MethodInvoker {
+    Object invoke(Object target, Object... parameters)
+        throws IllegalAccessException, InvocationTargetException;
+  }
+
+  /** Cached constructor injectors for each type */
+  final ConstructorInjectorStore constructors = new ConstructorInjectorStore(this);
+
+  /** Cached field and method injectors for each type. */
+  MembersInjectorStore membersInjectorStore;
+
+  /** Cached provision listener callbacks for each key. */
+  ProvisionListenerCallbackStore provisionListenerStore;
+
+  @SuppressWarnings("unchecked") // the members injector type is consistent with instance's type
+  public void injectMembers(Object instance) {
+    MembersInjector membersInjector = getMembersInjector(instance.getClass());
+    membersInjector.injectMembers(instance);
+  }
+
+  public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) {
+    Errors errors = new Errors(typeLiteral);
+    try {
+      return membersInjectorStore.get(typeLiteral, errors);
+    } catch (ErrorsException e) {
+      throw new ConfigurationException(errors.merge(e.getErrors()).getMessages());
+    }
+  }
+
+  public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
+    return getMembersInjector(TypeLiteral.get(type));
+  }
+
+  public <T> Provider<T> getProvider(Class<T> type) {
+    return getProvider(Key.get(type));
+  }
+
+  <T> Provider<T> getProviderOrThrow(final Dependency<T> dependency, Errors errors) throws ErrorsException {
+    final Key<T> key = dependency.getKey();
+    final BindingImpl<? extends T> binding = getBindingOrThrow(key, errors, JitLimitation.NO_JIT);
+
+    return new Provider<T>() {
+      public T get() {
+        final Errors errors = new Errors(dependency);
+        try {
+          T t = callInContext(new ContextualCallable<T>() {
+            public T call(InternalContext context) throws ErrorsException {
+              Dependency previous = context.pushDependency(dependency, binding.getSource());
+              try {
+                return binding.getInternalFactory().get(errors, context, dependency, false);
+              } finally {
+                context.popStateAndSetDependency(previous);
+              }
+            }
+          });
+          errors.throwIfNewErrors(0);
+          return t;
+        } catch (ErrorsException e) {
+          throw new ProvisionException(errors.merge(e.getErrors()).getMessages());
+        }
+      }
+
+      @Override public String toString() {
+        return binding.getInternalFactory().toString();
+      }
+    };
+  }
+
+  public <T> Provider<T> getProvider(final Key<T> key) {
+    Errors errors = new Errors(key);
+    try {
+      Provider<T> result = getProviderOrThrow(Dependency.get(key), errors);
+      errors.throwIfNewErrors(0);
+      return result;
+    } catch (ErrorsException e) {
+      throw new ConfigurationException(errors.merge(e.getErrors()).getMessages());
+    }
+  }
+
+  public <T> T getInstance(Key<T> key) {
+    return getProvider(key).get();
+  }
+
+  public <T> T getInstance(Class<T> type) {
+    return getProvider(type).get();
+  }
+
+  /** @see #getGlobalInternalContext */
+  private final ThreadLocal<Object[]> localContext;
+  /**
+   * Synchronization: map value is modified only for the current thread,
+   * it's ok to read map values of other threads. It can change between your
+   * calls.
+   *
+   * @see #getGlobalInternalContext
+   */
+  private static final ConcurrentMap<Thread, InternalContext> globalInternalContext =
+      Maps.newConcurrentMap();
+
+  /**
+   * Provides access to the internal context for the current injector of all threads.
+   * One does not need to use this from Guice source code as context could be passed on the stack.
+   * It is required for custom scopes which are called from Guice and sometimes do require
+   * access to current internal context, but it is not passed in. Contrary to {@link #localContext}
+   * it is not used to store injector-specific state, but to provide easy access to the current
+   * state.
+   *
+   * @return unmodifiable map
+   */
+  static Map<Thread, InternalContext> getGlobalInternalContext() {
+    return Collections.unmodifiableMap(globalInternalContext);
+  }
+
+  /** Looks up thread local context. Creates (and removes) a new context if necessary. */
+  <T> T callInContext(ContextualCallable<T> callable) throws ErrorsException {
+    Object[] reference = localContext.get();
+    if (reference == null) {
+      reference = new Object[1];
+      localContext.set(reference);
+    }
+    Thread currentThread = Thread.currentThread();
+    if (reference[0] == null) {
+      reference[0] = new InternalContext(options);
+      globalInternalContext.put(currentThread, (InternalContext) reference[0]);
+      try {
+        return callable.call((InternalContext) reference[0]);
+      } finally {
+        // Only clear contexts if this call created them.
+        reference[0] = null;
+        globalInternalContext.remove(currentThread);
+      }
+    } else {
+      Object previousGlobalInternalContext = globalInternalContext.get(currentThread);
+      globalInternalContext.put(currentThread, (InternalContext) reference[0]);
+      try {
+        // Someone else will clean up this local context.
+        return callable.call((InternalContext) reference[0]);
+      } finally {
+        if (previousGlobalInternalContext != null) {
+          globalInternalContext.put(currentThread, (InternalContext) previousGlobalInternalContext);
+        } else {
+          globalInternalContext.remove(currentThread);
+        }
+      }
+    }
+  }
+
+  @Override
+  public String toString() {
+    return Objects.toStringHelper(Injector.class)
+        .add("bindings", state.getExplicitBindingsThisLevel().values())
+        .toString();
+  }
+}
diff --git a/core/src/com/google/inject/internal/InjectorOptionsProcessor.java b/core/src/com/google/inject/internal/InjectorOptionsProcessor.java
new file mode 100644
index 0000000..61cc6ee
--- /dev/null
+++ b/core/src/com/google/inject/internal/InjectorOptionsProcessor.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.inject.Stage;
+import com.google.inject.internal.InjectorImpl.InjectorOptions;
+import com.google.inject.spi.DisableCircularProxiesOption;
+import com.google.inject.spi.RequireAtInjectOnConstructorsOption;
+import com.google.inject.spi.RequireExactBindingAnnotationsOption;
+import com.google.inject.spi.RequireExplicitBindingsOption;
+
+/**
+ * A processor to gather injector options.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+class InjectorOptionsProcessor extends AbstractProcessor {
+
+  private boolean disableCircularProxies = false;
+  private boolean jitDisabled = false;
+  private boolean atInjectRequired = false;
+  private boolean exactBindingAnnotationsRequired = false;
+
+  InjectorOptionsProcessor(Errors errors) {
+    super(errors);
+  }
+
+  @Override
+  public Boolean visit(DisableCircularProxiesOption option) {
+    disableCircularProxies = true;
+    return true;
+  }
+
+  @Override
+  public Boolean visit(RequireExplicitBindingsOption option) {
+    jitDisabled = true;
+    return true;
+  }
+  
+  @Override
+  public Boolean visit(RequireAtInjectOnConstructorsOption option) {
+    atInjectRequired = true;
+    return true;    
+  }
+
+  @Override
+  public Boolean visit(RequireExactBindingAnnotationsOption option) {
+    exactBindingAnnotationsRequired = true;
+    return true;
+  }
+
+  InjectorOptions getOptions(Stage stage, InjectorOptions parentOptions) {
+    checkNotNull(stage, "stage must be set");
+    if(parentOptions == null) {
+      return new InjectorOptions(
+          stage,
+          jitDisabled,
+          disableCircularProxies,
+          atInjectRequired,
+          exactBindingAnnotationsRequired);
+    } else {
+      checkState(stage == parentOptions.stage, "child & parent stage don't match");
+      return new InjectorOptions(
+          stage,
+          jitDisabled || parentOptions.jitDisabled,
+          disableCircularProxies || parentOptions.disableCircularProxies,
+          atInjectRequired || parentOptions.atInjectRequired,
+          exactBindingAnnotationsRequired || parentOptions.exactBindingAnnotationsRequired);
+    }
+  }
+
+}
diff --git a/core/src/com/google/inject/internal/InjectorShell.java b/core/src/com/google/inject/internal/InjectorShell.java
new file mode 100644
index 0000000..5982bb3
--- /dev/null
+++ b/core/src/com/google/inject/internal/InjectorShell.java
@@ -0,0 +1,312 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.inject.Scopes.SINGLETON;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.Binder;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.Stage;
+import com.google.inject.internal.InjectorImpl.InjectorOptions;
+import com.google.inject.internal.util.SourceProvider;
+import com.google.inject.internal.util.Stopwatch;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding;
+import com.google.inject.spi.PrivateElements;
+import com.google.inject.spi.ProvisionListenerBinding;
+import com.google.inject.spi.TypeListenerBinding;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * A partially-initialized injector. See {@link InternalInjectorCreator}, which
+ * uses this to build a tree of injectors in batch.
+ * 
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class InjectorShell {
+
+  private final List<Element> elements;
+  private final InjectorImpl injector;
+
+  private InjectorShell(Builder builder, List<Element> elements, InjectorImpl injector) {
+    this.elements = elements;
+    this.injector = injector;
+  }
+
+  InjectorImpl getInjector() {
+    return injector;
+  }
+
+  List<Element> getElements() {
+    return elements;
+  }
+
+  static class Builder {
+    private final List<Element> elements = Lists.newArrayList();
+    private final List<Module> modules = Lists.newArrayList();
+
+    /** lazily constructed */
+    private State state;
+
+    private InjectorImpl parent;
+    private InjectorOptions options;
+    private Stage stage;
+
+    /** null unless this exists in a {@link Binder#newPrivateBinder private environment} */
+    private PrivateElementsImpl privateElements;
+    
+    Builder stage(Stage stage) {
+      this.stage = stage;
+      return this;
+    }
+
+    Builder parent(InjectorImpl parent) {
+      this.parent = parent;
+      this.state = new InheritingState(parent.state);
+      this.options = parent.options;
+      this.stage = options.stage;
+      return this;
+    }
+
+    Builder privateElements(PrivateElements privateElements) {
+      this.privateElements = (PrivateElementsImpl) privateElements;
+      this.elements.addAll(privateElements.getElements());
+      return this;
+    }
+
+    void addModules(Iterable<? extends Module> modules) {
+      for (Module module : modules) {
+        this.modules.add(module);
+      }
+    }
+    
+    Stage getStage() {
+      return options.stage;
+    }
+
+    /** Synchronize on this before calling {@link #build}. */
+    Object lock() {
+      return getState().lock();
+    }
+
+    /**
+     * Creates and returns the injector shells for the current modules. Multiple shells will be
+     * returned if any modules contain {@link Binder#newPrivateBinder private environments}. The
+     * primary injector will be first in the returned list.
+     */
+    List<InjectorShell> build(
+        Initializer initializer,
+        ProcessedBindingData bindingData,
+        Stopwatch stopwatch,
+        Errors errors) {
+      checkState(stage != null, "Stage not initialized");
+      checkState(privateElements == null || parent != null, "PrivateElements with no parent");
+      checkState(state != null, "no state. Did you remember to lock() ?");
+
+      // bind Singleton if this is a top-level injector
+      if (parent == null) {
+        modules.add(0, new RootModule());
+      } else {
+        modules.add(0, new InheritedScannersModule(parent.state));
+      }
+      elements.addAll(Elements.getElements(stage, modules));
+      
+      // Look for injector-changing options
+      InjectorOptionsProcessor optionsProcessor = new InjectorOptionsProcessor(errors);
+      optionsProcessor.process(null, elements);
+      options = optionsProcessor.getOptions(stage, options);
+      
+      InjectorImpl injector = new InjectorImpl(parent, state, options);
+      if (privateElements != null) {
+        privateElements.initInjector(injector);
+      }
+
+      // add default type converters if this is a top-level injector
+      if (parent == null) {
+        TypeConverterBindingProcessor.prepareBuiltInConverters(injector);
+      }
+
+      stopwatch.resetAndLog("Module execution");
+
+      new MessageProcessor(errors).process(injector, elements);
+
+      /*if[AOP]*/
+      new InterceptorBindingProcessor(errors).process(injector, elements);
+      stopwatch.resetAndLog("Interceptors creation");
+      /*end[AOP]*/
+
+      new ListenerBindingProcessor(errors).process(injector, elements);
+      List<TypeListenerBinding> typeListenerBindings = injector.state.getTypeListenerBindings();
+      injector.membersInjectorStore = new MembersInjectorStore(injector, typeListenerBindings);
+      List<ProvisionListenerBinding> provisionListenerBindings =
+          injector.state.getProvisionListenerBindings();
+      injector.provisionListenerStore =
+          new ProvisionListenerCallbackStore(provisionListenerBindings);
+      stopwatch.resetAndLog("TypeListeners & ProvisionListener creation");
+
+      new ScopeBindingProcessor(errors).process(injector, elements);
+      stopwatch.resetAndLog("Scopes creation");
+
+      new TypeConverterBindingProcessor(errors).process(injector, elements);
+      stopwatch.resetAndLog("Converters creation");
+
+      bindStage(injector, stage);
+      bindInjector(injector);
+      bindLogger(injector);
+      
+      // Process all normal bindings, then UntargettedBindings.
+      // This is necessary because UntargettedBindings can create JIT bindings
+      // and need all their other dependencies set up ahead of time.
+      new BindingProcessor(errors, initializer, bindingData).process(injector, elements);
+      new UntargettedBindingProcessor(errors, bindingData).process(injector, elements);
+      stopwatch.resetAndLog("Binding creation");
+
+      new ModuleAnnotatedMethodScannerProcessor(errors).process(injector, elements);
+      stopwatch.resetAndLog("Module annotated method scanners creation");
+
+      List<InjectorShell> injectorShells = Lists.newArrayList();
+      injectorShells.add(new InjectorShell(this, elements, injector));
+
+      // recursively build child shells
+      PrivateElementProcessor processor = new PrivateElementProcessor(errors);
+      processor.process(injector, elements);
+      for (Builder builder : processor.getInjectorShellBuilders()) {
+        injectorShells.addAll(builder.build(initializer, bindingData, stopwatch, errors));
+      }
+      stopwatch.resetAndLog("Private environment creation");
+
+      return injectorShells;
+    }
+
+    private State getState() {
+      if (state == null) {
+        state = new InheritingState(State.NONE);
+      }
+      return state;
+    }
+  }
+
+  /**
+   * The Injector is a special case because we allow both parent and child injectors to both have
+   * a binding for that key.
+   */
+  private static void bindInjector(InjectorImpl injector) {
+    Key<Injector> key = Key.get(Injector.class);
+    InjectorFactory injectorFactory = new InjectorFactory(injector);
+    injector.state.putBinding(key,
+        new ProviderInstanceBindingImpl<Injector>(injector, key, SourceProvider.UNKNOWN_SOURCE,
+            injectorFactory, Scoping.UNSCOPED, injectorFactory,
+            ImmutableSet.<InjectionPoint>of()));
+  }
+
+  private static class InjectorFactory implements InternalFactory<Injector>, Provider<Injector> {
+    private final Injector injector;
+
+    private InjectorFactory(Injector injector) {
+      this.injector = injector;
+    }
+
+    public Injector get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+        throws ErrorsException {
+      return injector;
+    }
+
+    public Injector get() {
+      return injector;
+    }
+
+    public String toString() {
+      return "Provider<Injector>";
+    }
+  }
+
+  /**
+   * The Logger is a special case because it knows the injection point of the injected member. It's
+   * the only binding that does this.
+   */
+  private static void bindLogger(InjectorImpl injector) {
+    Key<Logger> key = Key.get(Logger.class);
+    LoggerFactory loggerFactory = new LoggerFactory();
+    injector.state.putBinding(key,
+        new ProviderInstanceBindingImpl<Logger>(injector, key,
+            SourceProvider.UNKNOWN_SOURCE, loggerFactory, Scoping.UNSCOPED,
+            loggerFactory, ImmutableSet.<InjectionPoint>of()));
+  }
+
+  private static class LoggerFactory implements InternalFactory<Logger>, Provider<Logger> {
+    public Logger get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) {
+      InjectionPoint injectionPoint = dependency.getInjectionPoint();
+      return injectionPoint == null
+          ? Logger.getAnonymousLogger()
+          : Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
+    }
+
+    public Logger get() {
+      return Logger.getAnonymousLogger();
+    }
+
+    public String toString() {
+      return "Provider<Logger>";
+    }
+  }
+  
+  private static void bindStage(InjectorImpl injector, Stage stage) {
+    Key<Stage> key = Key.get(Stage.class);
+    InstanceBindingImpl<Stage> stageBinding = new InstanceBindingImpl<Stage>(
+        injector,
+        key,
+        SourceProvider.UNKNOWN_SOURCE,
+        new ConstantFactory<Stage>(Initializables.of(stage)),
+        ImmutableSet.<InjectionPoint>of(),
+        stage);
+    injector.state.putBinding(key, stageBinding);
+  }
+
+  private static class RootModule implements Module {
+    public void configure(Binder binder) {
+      binder = binder.withSource(SourceProvider.UNKNOWN_SOURCE);
+      binder.bindScope(Singleton.class, SINGLETON);
+      binder.bindScope(javax.inject.Singleton.class, SINGLETON);
+    }
+  }
+
+  private static class InheritedScannersModule implements Module {
+    private final State state;
+
+    InheritedScannersModule(State state) {
+      this.state = state;
+    }
+
+    public void configure(Binder binder) {
+      for (ModuleAnnotatedMethodScannerBinding binding : state.getScannerBindings()) {
+        binding.applyTo(binder);
+      }
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/InstanceBindingImpl.java b/core/src/com/google/inject/internal/InstanceBindingImpl.java
new file mode 100644
index 0000000..9b7a483
--- /dev/null
+++ b/core/src/com/google/inject/internal/InstanceBindingImpl.java
@@ -0,0 +1,115 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.util.Providers;
+
+import java.util.Set;
+
+final class InstanceBindingImpl<T> extends BindingImpl<T> implements InstanceBinding<T> {
+
+  final T instance;
+  final Provider<T> provider;
+  final ImmutableSet<InjectionPoint> injectionPoints;
+
+  public InstanceBindingImpl(InjectorImpl injector, Key<T> key, Object source,
+      InternalFactory<? extends T> internalFactory, Set<InjectionPoint> injectionPoints,
+      T instance) {
+    super(injector, key, source, internalFactory, Scoping.EAGER_SINGLETON);
+    this.injectionPoints = ImmutableSet.copyOf(injectionPoints);
+    this.instance = instance;
+    this.provider = Providers.of(instance);
+  }
+
+  public InstanceBindingImpl(Object source, Key<T> key, Scoping scoping,
+      Set<InjectionPoint> injectionPoints, T instance) {
+    super(source, key, scoping);
+    this.injectionPoints = ImmutableSet.copyOf(injectionPoints);
+    this.instance = instance;
+    this.provider = Providers.of(instance);
+  }
+
+  @Override public Provider<T> getProvider() {
+    return this.provider;
+  }
+
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
+    return visitor.visit(this);
+  }
+
+  public T getInstance() {
+    return instance;
+  }
+
+  public Set<InjectionPoint> getInjectionPoints() {
+    return injectionPoints;
+  }
+
+  public Set<Dependency<?>> getDependencies() {
+    return instance instanceof HasDependencies
+        ? ImmutableSet.copyOf(((HasDependencies) instance).getDependencies())
+        : Dependency.forInjectionPoints(injectionPoints);
+  }
+
+  public BindingImpl<T> withScoping(Scoping scoping) {
+    return new InstanceBindingImpl<T>(getSource(), getKey(), scoping, injectionPoints, instance);
+  }
+
+  public BindingImpl<T> withKey(Key<T> key) {
+    return new InstanceBindingImpl<T>(getSource(), key, getScoping(), injectionPoints, instance);
+  }
+
+  public void applyTo(Binder binder) {
+    // instance bindings aren't scoped
+    binder.withSource(getSource()).bind(getKey()).toInstance(instance);
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(InstanceBinding.class)
+        .add("key", getKey())
+        .add("source", getSource())
+        .add("instance", instance)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if(obj instanceof InstanceBindingImpl) {
+      InstanceBindingImpl<?> o = (InstanceBindingImpl<?>)obj;
+      return getKey().equals(o.getKey())
+        && getScoping().equals(o.getScoping())
+        && Objects.equal(instance, o.instance);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(getKey(), getScoping());
+  }
+}
diff --git a/core/src/com/google/inject/internal/InterceptorBindingProcessor.java b/core/src/com/google/inject/internal/InterceptorBindingProcessor.java
new file mode 100644
index 0000000..e352672
--- /dev/null
+++ b/core/src/com/google/inject/internal/InterceptorBindingProcessor.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.spi.InterceptorBinding;
+
+/**
+ * Handles {@code Binder.bindInterceptor} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class InterceptorBindingProcessor extends AbstractProcessor {
+
+  InterceptorBindingProcessor(Errors errors) {
+    super(errors);
+  }
+
+  @Override public Boolean visit(InterceptorBinding command) {
+    injector.state.addMethodAspect(new MethodAspect(
+        command.getClassMatcher(), command.getMethodMatcher(), command.getInterceptors()));
+    return true;
+  }
+}
diff --git a/core/src/com/google/inject/internal/InterceptorStackCallback.java b/core/src/com/google/inject/internal/InterceptorStackCallback.java
new file mode 100644
index 0000000..f12ddaf
--- /dev/null
+++ b/core/src/com/google/inject/internal/InterceptorStackCallback.java
@@ -0,0 +1,119 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.Lists;
+
+import net.sf.cglib.proxy.MethodProxy;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Intercepts a method with a stack of interceptors.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class InterceptorStackCallback implements net.sf.cglib.proxy.MethodInterceptor {
+  private static final Set<String> AOP_INTERNAL_CLASSES = new HashSet<String>(Arrays.asList(
+      InterceptorStackCallback.class.getName(),
+      InterceptedMethodInvocation.class.getName(),
+      MethodProxy.class.getName()));
+
+  final MethodInterceptor[] interceptors;
+  final Method method;
+
+  public InterceptorStackCallback(Method method,
+      List<MethodInterceptor> interceptors) {
+    this.method = method;
+    this.interceptors = interceptors.toArray(new MethodInterceptor[interceptors.size()]);
+  }
+
+  public Object intercept(Object proxy, Method method, Object[] arguments,
+      MethodProxy methodProxy) throws Throwable {
+    return new InterceptedMethodInvocation(proxy, methodProxy, arguments, 0).proceed();
+  }
+
+  private class InterceptedMethodInvocation implements MethodInvocation {
+
+    final Object proxy;
+    final Object[] arguments;
+    final MethodProxy methodProxy;
+    final int index;
+
+    public InterceptedMethodInvocation(Object proxy, MethodProxy methodProxy,
+        Object[] arguments, int index) {
+      this.proxy = proxy;
+      this.methodProxy = methodProxy;
+      this.arguments = arguments;
+      this.index = index;
+    }
+
+    public Object proceed() throws Throwable {
+      try {
+        return index == interceptors.length
+            ? methodProxy.invokeSuper(proxy, arguments)
+            : interceptors[index].invoke(
+                new InterceptedMethodInvocation(proxy, methodProxy, arguments, index + 1));
+      } catch (Throwable t) {
+        pruneStacktrace(t);
+        throw t;
+      }
+    }
+
+    public Method getMethod() {
+      return method;
+    }
+
+    public Object[] getArguments() {
+      return arguments;
+    }
+
+    public Object getThis() {
+      return proxy;
+    }
+
+    public AccessibleObject getStaticPart() {
+      return getMethod();
+    }
+  }
+
+  /**
+   * Removes stacktrace elements related to AOP internal mechanics from the
+   * throwable's stack trace and any causes it may have.
+   */
+  private void pruneStacktrace(Throwable throwable) {
+    for(Throwable t = throwable; t != null; t = t.getCause()) {
+      StackTraceElement[] stackTrace = t.getStackTrace();
+      List<StackTraceElement> pruned = Lists.newArrayList();
+      for (StackTraceElement element : stackTrace) {
+        String className = element.getClassName();
+        if (!AOP_INTERNAL_CLASSES.contains(className) && !className.contains("$EnhancerByGuice$")) {
+          pruned.add(element);
+        }
+      }
+      t.setStackTrace(pruned.toArray(new StackTraceElement[pruned.size()]));
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/InternalContext.java b/core/src/com/google/inject/internal/InternalContext.java
new file mode 100644
index 0000000..0af1969
--- /dev/null
+++ b/core/src/com/google/inject/internal/InternalContext.java
@@ -0,0 +1,144 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Key;
+import com.google.inject.internal.InjectorImpl.InjectorOptions;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.DependencyAndSource;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Internal context. Used to coordinate injections and support circular
+ * dependencies.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class InternalContext {
+
+  private final InjectorOptions options;
+
+  private Map<Object, ConstructionContext<?>> constructionContexts = Maps.newHashMap();
+
+  /** Keeps track of the type that is currently being requested for injection. */
+  private Dependency<?> dependency;
+
+  /** Keeps track of the hierarchy of types needed during injection. */
+  private final DependencyStack state = new DependencyStack();
+
+  InternalContext(InjectorOptions options) {
+    this.options = options;
+  }
+
+  public InjectorOptions getInjectorOptions() {
+    return options;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T> ConstructionContext<T> getConstructionContext(Object key) {
+    ConstructionContext<T> constructionContext
+        = (ConstructionContext<T>) constructionContexts.get(key);
+    if (constructionContext == null) {
+      constructionContext = new ConstructionContext<T>();
+      constructionContexts.put(key, constructionContext);
+    }
+    return constructionContext;
+  }
+
+  public Dependency<?> getDependency() {
+    return dependency;
+  }
+
+  /** Sets the new current dependency & adds it to the state. */
+  public Dependency<?> pushDependency(Dependency<?> dependency, Object source) {
+    Dependency<?> previous = this.dependency;
+    this.dependency = dependency;
+    state.add(dependency, source);
+    return previous;
+  }
+
+  /** Pops the current state & sets the new dependency. */
+  public void popStateAndSetDependency(Dependency<?> newDependency) {
+    state.pop();
+    this.dependency = newDependency;
+  }
+
+  /** Adds to the state without setting the dependency. */
+  public void pushState(Key<?> key, Object source) {
+    state.add(key, source);
+  }
+  
+  /** Pops from the state without setting a dependency. */
+  public void popState() {
+    state.pop();
+  }
+
+  /** Returns the current dependency chain (all the state). */
+  public List<DependencyAndSource> getDependencyChain() {
+    ImmutableList.Builder<DependencyAndSource> builder = ImmutableList.builder();
+    for (int i = 0; i < state.size(); i += 2) {
+      Object evenEntry = state.get(i);
+      Dependency<?> dependency;
+      if (evenEntry instanceof Key) {
+        dependency = Dependency.get((Key<?>) evenEntry);
+      } else {
+        dependency = (Dependency<?>) evenEntry;
+      }
+      builder.add(new DependencyAndSource(dependency, state.get(i + 1)));
+    }
+    return builder.build();
+  }
+
+  /**
+   * Keeps track of the hierarchy of types needed during injection.
+   *
+   * <p>This is a pairwise combination of dependencies and sources, with dependencies or keys on
+   * even indices, and sources on odd indices. This structure is to avoid the memory overhead of
+   * DependencyAndSource objects, which can add to several tens of megabytes in large applications.
+   */
+  private static final class DependencyStack {
+    private Object[] elements = new Object[16];
+    private int size = 0;
+
+    public void add(Object dependencyOrKey, Object source) {
+      if (elements.length < size + 2) {
+        elements = Arrays.copyOf(elements, (elements.length*3)/2 + 2);
+      }
+      elements[size++] = dependencyOrKey;
+      elements[size++] = source;
+    }
+
+    public void pop() {
+      elements[--size] = null;
+      elements[--size] = null;
+    }
+
+    public Object get(int i) {
+      return elements[i];
+    }
+
+    public int size() {
+      return size;
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/InternalFactory.java b/core/src/com/google/inject/internal/InternalFactory.java
new file mode 100644
index 0000000..2267b12
--- /dev/null
+++ b/core/src/com/google/inject/internal/InternalFactory.java
@@ -0,0 +1,38 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.inject.spi.Dependency;
+
+/**
+ * Creates objects which will be injected.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+interface InternalFactory<T> {
+
+  /**
+   * Creates an object to be injected.
+   * @param context of this injection
+   * @param linked true if getting as a result of a linked binding
+   *
+   * @throws com.google.inject.internal.ErrorsException if a value cannot be provided
+   * @return instance to be injected
+   */
+  T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+      throws ErrorsException;
+}
diff --git a/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java b/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java
new file mode 100644
index 0000000..c02c70e
--- /dev/null
+++ b/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.ProviderInstanceBinding;
+
+/**
+ * Adapts {@link ProviderInstanceBinding} providers, ensuring circular proxies
+ * fail (or proxy) properly.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+*/
+final class InternalFactoryToInitializableAdapter<T> extends ProviderInternalFactory<T> {
+
+  private final ProvisionListenerStackCallback<T> provisionCallback;
+  private final Initializable<? extends javax.inject.Provider<? extends T>> initializable;
+
+  public InternalFactoryToInitializableAdapter(
+      Initializable<? extends javax.inject.Provider<? extends T>> initializable,
+      Object source, ProvisionListenerStackCallback<T> provisionCallback) {
+    super(source);
+    this.provisionCallback = checkNotNull(provisionCallback, "provisionCallback");
+    this.initializable = checkNotNull(initializable, "provider");
+  }
+
+  public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+      throws ErrorsException {
+    return circularGet(initializable.get(errors), errors, context, dependency,
+        provisionCallback);
+  }
+  
+  @Override
+  protected T provision(javax.inject.Provider<? extends T> provider, Errors errors,
+      Dependency<?> dependency, ConstructionContext<T> constructionContext) throws ErrorsException {
+    try {
+      return super.provision(provider, errors, dependency, constructionContext);
+    } catch(RuntimeException userException) {
+      throw errors.withSource(source).errorInProvider(userException).toException();
+    }
+  }
+
+  @Override public String toString() {
+    return initializable.toString();
+  }
+}
diff --git a/core/src/com/google/inject/internal/InternalFactoryToProviderAdapter.java b/core/src/com/google/inject/internal/InternalFactoryToProviderAdapter.java
new file mode 100644
index 0000000..4cd1b2e
--- /dev/null
+++ b/core/src/com/google/inject/internal/InternalFactoryToProviderAdapter.java
@@ -0,0 +1,50 @@
+/**
+ * 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 com.google.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Provider;
+import com.google.inject.spi.Dependency;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+*/
+final class InternalFactoryToProviderAdapter<T> implements InternalFactory<T> {
+
+  private final Provider<? extends T> provider;
+  private final Object source;
+
+  public InternalFactoryToProviderAdapter(Provider<? extends T> provider, Object source) {
+    this.provider = checkNotNull(provider, "provider");
+    this.source = checkNotNull(source, "source");
+  }
+
+  public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
+      throws ErrorsException {
+    // TODO(sameb): Does this need to push state into the context?
+    try {
+      return errors.checkForNull(provider.get(), source, dependency);
+    } catch (RuntimeException userException) {
+      throw errors.withSource(source).errorInProvider(userException).toException();
+    }
+  }
+
+  @Override public String toString() {
+    return provider.toString();
+  }
+}
diff --git a/core/src/com/google/inject/internal/InternalFlags.java b/core/src/com/google/inject/internal/InternalFlags.java
new file mode 100644
index 0000000..85c07ac
--- /dev/null
+++ b/core/src/com/google/inject/internal/InternalFlags.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright (C) 2013 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.inject.internal;
+
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.logging.Logger;
+/**
+ * Contains flags for Guice.
+ */
+public class InternalFlags {
+  private static final Logger logger = Logger.getLogger(InternalFlags.class.getName());
+
+  private static final IncludeStackTraceOption INCLUDE_STACK_TRACES
+      = parseIncludeStackTraceOption();
+
+  private static final CustomClassLoadingOption CUSTOM_CLASS_LOADING
+      = parseCustomClassLoadingOption();
+
+  private static final NullableProvidesOption NULLABLE_PROVIDES
+      = parseNullableProvidesOption(NullableProvidesOption.ERROR);
+
+
+  /**
+   * The options for Guice stack trace collection.
+   */
+  public enum IncludeStackTraceOption {
+    /** No stack trace collection */
+    OFF,
+    /**  Minimum stack trace collection (Default) */
+    ONLY_FOR_DECLARING_SOURCE,
+    /** Full stack trace for everything */
+    COMPLETE
+  }
+
+  /**
+   * The options for Guice custom class loading.
+   */
+  public enum CustomClassLoadingOption {
+    /** No custom class loading */
+    OFF,
+    /** Automatically bridge between class loaders (Default) */
+    BRIDGE
+  }
+
+  public enum NullableProvidesOption {
+    /** Ignore null parameters to @Provides methods. */
+    IGNORE,
+    /** Warn if null parameters are passed to non-@Nullable parameters of provides methods. */
+    WARN,
+    /** Error if null parameters are passed to non-@Nullable parameters of provides parameters */
+    ERROR
+  }
+
+  public static IncludeStackTraceOption getIncludeStackTraceOption() {
+    return INCLUDE_STACK_TRACES;
+  }
+
+  public static CustomClassLoadingOption getCustomClassLoadingOption() {
+    return CUSTOM_CLASS_LOADING;
+  }
+
+  public static NullableProvidesOption getNullableProvidesOption() {
+    return NULLABLE_PROVIDES;
+  }
+
+  private static IncludeStackTraceOption parseIncludeStackTraceOption() {
+    return getSystemOption("guice_include_stack_traces",
+        IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE);
+  }
+
+  private static CustomClassLoadingOption parseCustomClassLoadingOption() {
+    return getSystemOption("guice_custom_class_loading",
+        CustomClassLoadingOption.BRIDGE, CustomClassLoadingOption.OFF);
+  }
+
+  private static NullableProvidesOption parseNullableProvidesOption(
+      NullableProvidesOption defaultValue) {
+    return getSystemOption("guice_check_nullable_provides_params", defaultValue);
+  }
+
+  /**
+   * Gets the system option indicated by the specified key; runs as a privileged action.
+   *
+   * @param name of the system option
+   * @param defaultValue if the option is not set
+   *
+   * @return value of the option, defaultValue if not set
+   */
+  private static <T extends Enum<T>> T getSystemOption(final String name, T defaultValue) {
+    return getSystemOption(name, defaultValue, defaultValue);
+  }
+
+  /**
+   * Gets the system option indicated by the specified key; runs as a privileged action.
+   *
+   * @param name of the system option
+   * @param defaultValue if the option is not set
+   * @param secureValue if the security manager disallows access to the option
+   *
+   * @return value of the option, defaultValue if not set, secureValue if no access
+   */
+  private static <T extends Enum<T>> T getSystemOption(final String name, T defaultValue,
+      T secureValue) {
+    Class<T> enumType = defaultValue.getDeclaringClass();
+    String value = null;
+    try {
+      value = AccessController.doPrivileged(new PrivilegedAction<String>() {
+        public String run() {
+          return System.getProperty(name);
+        }
+      });
+      return (value != null && value.length() > 0) ? Enum.valueOf(enumType, value) : defaultValue;
+    } catch (SecurityException e) {
+      return secureValue;
+    } catch (IllegalArgumentException e) {
+      logger.warning(value + " is not a valid flag value for " + name + ". "
+          + " Values must be one of " + Arrays.asList(enumType.getEnumConstants()));
+      return defaultValue;
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/InternalInjectorCreator.java b/core/src/com/google/inject/internal/InternalInjectorCreator.java
new file mode 100644
index 0000000..d40bc83
--- /dev/null
+++ b/core/src/com/google/inject/internal/InternalInjectorCreator.java
@@ -0,0 +1,307 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.util.Stopwatch;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.TypeConverterBinding;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Builds a tree of injectors. This is a primary injector, plus child injectors needed for each
+ * {@code Binder.newPrivateBinder() private environment}. The primary injector is not necessarily a
+ * top-level injector.
+ *
+ * <p>Injector construction happens in two phases.
+ * <ol>
+ *   <li>Static building. In this phase, we interpret commands, create bindings, and inspect 
+ *     dependencies. During this phase, we hold a lock to ensure consistency with parent injectors.
+ *     No user code is executed in this phase.</li>
+ *   <li>Dynamic injection. In this phase, we call user code. We inject members that requested
+ *     injection. This may require user's objects be created and their providers be called. And we
+ *     create eager singletons. In this phase, user code may have started other threads. This phase
+ *     is not executed for injectors created using {@link Stage#TOOL the tool stage}</li>
+ * </ol>
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public final class InternalInjectorCreator {
+
+  private final Stopwatch stopwatch = new Stopwatch();
+  private final Errors errors = new Errors();
+
+  private final Initializer initializer = new Initializer();
+  private final ProcessedBindingData bindingData;
+  private final InjectionRequestProcessor injectionRequestProcessor;
+
+  private final InjectorShell.Builder shellBuilder = new InjectorShell.Builder();
+  private List<InjectorShell> shells;
+  
+  public InternalInjectorCreator() {
+    injectionRequestProcessor = new InjectionRequestProcessor(errors, initializer);
+    bindingData = new ProcessedBindingData();
+  }
+  
+  public InternalInjectorCreator stage(Stage stage) {
+    shellBuilder.stage(stage);
+    return this;
+  }
+
+  /**
+   * Sets the parent of the injector to-be-constructed. As a side effect, this sets this injector's
+   * stage to the stage of {@code parent} and sets {@link #requireExplicitBindings()} if the parent
+   * injector also required them.
+   */
+  public InternalInjectorCreator parentInjector(InjectorImpl parent) {
+    shellBuilder.parent(parent);
+    return this;
+  }
+
+  public InternalInjectorCreator addModules(Iterable<? extends Module> modules) {
+    shellBuilder.addModules(modules);
+    return this;
+  }
+
+  public Injector build() {
+    if (shellBuilder == null) {
+      throw new AssertionError("Already built, builders are not reusable.");
+    }
+
+    // Synchronize while we're building up the bindings and other injector state. This ensures that
+    // the JIT bindings in the parent injector don't change while we're being built
+    synchronized (shellBuilder.lock()) {
+      shells = shellBuilder.build(initializer, bindingData, stopwatch, errors);
+      stopwatch.resetAndLog("Injector construction");
+
+      initializeStatically();
+    }
+
+    injectDynamically();
+
+    if (shellBuilder.getStage() == Stage.TOOL) {
+      // wrap the primaryInjector in a ToolStageInjector
+      // to prevent non-tool-friendy methods from being called.
+      return new ToolStageInjector(primaryInjector());
+    } else {
+      return primaryInjector();
+    }
+  }
+
+  /** Initialize and validate everything. */
+  private void initializeStatically() {
+    bindingData.initializeBindings();
+    stopwatch.resetAndLog("Binding initialization");
+
+    for (InjectorShell shell : shells) {
+      shell.getInjector().index();
+    }
+    stopwatch.resetAndLog("Binding indexing");
+
+    injectionRequestProcessor.process(shells);
+    stopwatch.resetAndLog("Collecting injection requests");
+
+    bindingData.runCreationListeners(errors);
+    stopwatch.resetAndLog("Binding validation");
+
+    injectionRequestProcessor.validate();
+    stopwatch.resetAndLog("Static validation");
+
+    initializer.validateOustandingInjections(errors);
+    stopwatch.resetAndLog("Instance member validation");
+
+    new LookupProcessor(errors).process(shells);
+    for (InjectorShell shell : shells) {
+      ((DeferredLookups) shell.getInjector().lookups).initialize(errors);
+    }
+    stopwatch.resetAndLog("Provider verification");
+
+    for (InjectorShell shell : shells) {
+      if (!shell.getElements().isEmpty()) {
+        throw new AssertionError("Failed to execute " + shell.getElements());
+      }
+    }
+
+    errors.throwCreationExceptionIfErrorsExist();
+  }
+
+  /**
+   * Returns the injector being constructed. This is not necessarily the root injector.
+   */
+  private Injector primaryInjector() {
+    return shells.get(0).getInjector();
+  }
+
+  /**
+   * Inject everything that can be injected. This method is intentionally not synchronized. If we
+   * locked while injecting members (ie. running user code), things would deadlock should the user
+   * code build a just-in-time binding from another thread.
+   */
+  private void injectDynamically() {
+    injectionRequestProcessor.injectMembers();
+    stopwatch.resetAndLog("Static member injection");
+
+    initializer.injectAll(errors);
+    stopwatch.resetAndLog("Instance injection");
+    errors.throwCreationExceptionIfErrorsExist();
+
+    if(shellBuilder.getStage() != Stage.TOOL) {
+      for (InjectorShell shell : shells) {
+        loadEagerSingletons(shell.getInjector(), shellBuilder.getStage(), errors);
+      }
+      stopwatch.resetAndLog("Preloading singletons");
+    }
+    errors.throwCreationExceptionIfErrorsExist();
+  }
+
+  /**
+   * Loads eager singletons, or all singletons if we're in Stage.PRODUCTION. Bindings discovered
+   * while we're binding these singletons are not be eager.
+   */
+  void loadEagerSingletons(InjectorImpl injector, Stage stage, final Errors errors) {
+    @SuppressWarnings("unchecked") // casting Collection<Binding> to Collection<BindingImpl> is safe
+    Iterable<BindingImpl<?>> candidateBindings = ImmutableList.copyOf(Iterables.concat(
+        (Collection) injector.state.getExplicitBindingsThisLevel().values(),
+        injector.jitBindings.values()));
+    for (final BindingImpl<?> binding : candidateBindings) {
+      if (isEagerSingleton(injector, binding, stage)) {
+        try {
+          injector.callInContext(new ContextualCallable<Void>() {
+            Dependency<?> dependency = Dependency.get(binding.getKey());
+            public Void call(InternalContext context) {
+              Dependency previous = context.pushDependency(dependency, binding.getSource());
+              Errors errorsForBinding = errors.withSource(dependency);
+              try {
+                binding.getInternalFactory().get(errorsForBinding, context, dependency, false);
+              } catch (ErrorsException e) {
+                errorsForBinding.merge(e.getErrors());
+              } finally {
+                context.popStateAndSetDependency(previous);
+              }
+
+              return null;
+            }
+          });
+        } catch (ErrorsException e) {
+          throw new AssertionError();
+        }
+      }
+    }
+  }
+
+  private boolean isEagerSingleton(InjectorImpl injector, BindingImpl<?> binding, Stage stage) {
+    if (binding.getScoping().isEagerSingleton(stage)) {
+      return true;
+    }
+
+    // handle a corner case where a child injector links to a binding in a parent injector, and
+    // that binding is singleton. We won't catch this otherwise because we only iterate the child's
+    // bindings.
+    if (binding instanceof LinkedBindingImpl) {
+      Key<?> linkedBinding = ((LinkedBindingImpl<?>) binding).getLinkedKey();
+      return isEagerSingleton(injector, injector.getBinding(linkedBinding), stage);
+    }
+
+    return false;
+  }
+
+  /** {@link Injector} exposed to users in {@link Stage#TOOL}. */
+  static class ToolStageInjector implements Injector {
+    private final Injector delegateInjector;
+    
+    ToolStageInjector(Injector delegateInjector) {
+      this.delegateInjector = delegateInjector;
+    }
+    public void injectMembers(Object o) {
+      throw new UnsupportedOperationException(
+        "Injector.injectMembers(Object) is not supported in Stage.TOOL");
+    }
+    public Map<Key<?>, Binding<?>> getBindings() {
+      return this.delegateInjector.getBindings();
+    }
+    public Map<Key<?>, Binding<?>> getAllBindings() {
+      return this.delegateInjector.getAllBindings();
+    }
+    public <T> Binding<T> getBinding(Key<T> key) {
+      return this.delegateInjector.getBinding(key);
+    }
+    public <T> Binding<T> getBinding(Class<T> type) {
+      return this.delegateInjector.getBinding(type);
+    }
+    public <T> Binding<T> getExistingBinding(Key<T> key) {
+      return this.delegateInjector.getExistingBinding(key);
+    }
+    public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type) {
+      return this.delegateInjector.findBindingsByType(type);
+    }
+    public Injector getParent() {
+      return delegateInjector.getParent();
+    }
+    public Injector createChildInjector(Iterable<? extends Module> modules) {
+      return delegateInjector.createChildInjector(modules);
+    }
+    public Injector createChildInjector(Module... modules) {
+      return delegateInjector.createChildInjector(modules);
+    }
+    public Map<Class<? extends Annotation>, Scope> getScopeBindings() {
+      return delegateInjector.getScopeBindings();
+    }
+    public Set<TypeConverterBinding> getTypeConverterBindings() {
+      return delegateInjector.getTypeConverterBindings();
+    }
+    public <T> Provider<T> getProvider(Key<T> key) {
+      throw new UnsupportedOperationException(
+        "Injector.getProvider(Key<T>) is not supported in Stage.TOOL");
+    }
+    public <T> Provider<T> getProvider(Class<T> type) {
+      throw new UnsupportedOperationException(
+        "Injector.getProvider(Class<T>) is not supported in Stage.TOOL");
+    }
+    public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) {
+      throw new UnsupportedOperationException(
+        "Injector.getMembersInjector(TypeLiteral<T>) is not supported in Stage.TOOL");
+    }
+    public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
+      throw new UnsupportedOperationException(
+        "Injector.getMembersInjector(Class<T>) is not supported in Stage.TOOL");
+    }
+    public <T> T getInstance(Key<T> key) {
+      throw new UnsupportedOperationException(
+        "Injector.getInstance(Key<T>) is not supported in Stage.TOOL");
+    }
+    public <T> T getInstance(Class<T> type) {
+      throw new UnsupportedOperationException(
+        "Injector.getInstance(Class<T>) is not supported in Stage.TOOL");
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/LinkedBindingImpl.java b/core/src/com/google/inject/internal/LinkedBindingImpl.java
new file mode 100644
index 0000000..8f83324
--- /dev/null
+++ b/core/src/com/google/inject/internal/LinkedBindingImpl.java
@@ -0,0 +1,95 @@
+/*
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.LinkedKeyBinding;
+
+import java.util.Set;
+
+public final class LinkedBindingImpl<T> extends BindingImpl<T> implements LinkedKeyBinding<T>, HasDependencies {
+
+  final Key<? extends T> targetKey;
+
+  public LinkedBindingImpl(InjectorImpl injector, Key<T> key, Object source,
+      InternalFactory<? extends T> internalFactory, Scoping scoping,
+      Key<? extends T> targetKey) {
+    super(injector, key, source, internalFactory, scoping);
+    this.targetKey = targetKey;
+  }
+
+  public LinkedBindingImpl(Object source, Key<T> key, Scoping scoping, Key<? extends T> targetKey) {
+    super(source, key, scoping);
+    this.targetKey = targetKey;
+  }
+
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
+    return visitor.visit(this);
+  }
+
+  public Key<? extends T> getLinkedKey() {
+    return targetKey;
+  }
+
+  public Set<Dependency<?>> getDependencies() {
+    return ImmutableSet.<Dependency<?>>of(Dependency.get(targetKey));
+  }
+
+  public BindingImpl<T> withScoping(Scoping scoping) {
+    return new LinkedBindingImpl<T>(getSource(), getKey(), scoping, targetKey);
+  }
+
+  public BindingImpl<T> withKey(Key<T> key) {
+    return new LinkedBindingImpl<T>(getSource(), key, getScoping(), targetKey);
+  }
+
+  public void applyTo(Binder binder) {
+    getScoping().applyTo(binder.withSource(getSource()).bind(getKey()).to(getLinkedKey()));
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(LinkedKeyBinding.class)
+        .add("key", getKey())
+        .add("source", getSource())
+        .add("scope", getScoping())
+        .add("target", targetKey)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if(obj instanceof LinkedBindingImpl) {
+      LinkedBindingImpl<?> o = (LinkedBindingImpl<?>)obj;
+      return getKey().equals(o.getKey())
+        && getScoping().equals(o.getScoping())
+        && Objects.equal(targetKey, o.targetKey);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(getKey(), getScoping(), targetKey);
+  }
+}
diff --git a/core/src/com/google/inject/internal/LinkedProviderBindingImpl.java b/core/src/com/google/inject/internal/LinkedProviderBindingImpl.java
new file mode 100644
index 0000000..a4a78a5
--- /dev/null
+++ b/core/src/com/google/inject/internal/LinkedProviderBindingImpl.java
@@ -0,0 +1,122 @@
+/*
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.ProviderKeyBinding;
+
+import java.util.Set;
+
+final class LinkedProviderBindingImpl<T>
+    extends BindingImpl<T> implements ProviderKeyBinding<T>, HasDependencies, DelayedInitialize {
+
+  final Key<? extends javax.inject.Provider<? extends T>> providerKey;
+  final DelayedInitialize delayedInitializer;
+
+  private LinkedProviderBindingImpl(InjectorImpl injector, Key<T> key, Object source,
+      InternalFactory<? extends T> internalFactory, Scoping scoping,
+      Key<? extends javax.inject.Provider<? extends T>> providerKey,
+      DelayedInitialize delayedInitializer) {
+    super(injector, key, source, internalFactory, scoping);
+    this.providerKey = providerKey;
+    this.delayedInitializer = delayedInitializer;
+  }
+
+  public LinkedProviderBindingImpl(InjectorImpl injector, Key<T> key, Object source,
+      InternalFactory<? extends T> internalFactory, Scoping scoping,
+      Key<? extends javax.inject.Provider<? extends T>> providerKey) {
+    this(injector, key, source, internalFactory, scoping, providerKey, null);
+  }
+
+  LinkedProviderBindingImpl(Object source, Key<T> key, Scoping scoping,
+      Key<? extends javax.inject.Provider<? extends T>> providerKey) {
+    super(source, key, scoping);
+    this.providerKey = providerKey;
+    this.delayedInitializer = null;
+  }
+
+  static <T> LinkedProviderBindingImpl<T> createWithInitializer(InjectorImpl injector, Key<T> key,
+      Object source, InternalFactory<? extends T> internalFactory, Scoping scoping,
+      Key<? extends javax.inject.Provider<? extends T>> providerKey,
+      DelayedInitialize delayedInitializer) {
+    return new LinkedProviderBindingImpl<T>(injector, key, source, internalFactory, scoping,
+        providerKey, delayedInitializer);
+  }
+
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
+    return visitor.visit(this);
+  }
+
+  public Key<? extends javax.inject.Provider<? extends T>> getProviderKey() {
+    return providerKey;
+  }
+
+  public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
+    if (delayedInitializer != null) {
+      delayedInitializer.initialize(injector, errors);
+    }
+  }
+
+  public Set<Dependency<?>> getDependencies() {
+    return ImmutableSet.<Dependency<?>>of(Dependency.get(providerKey));
+  }
+
+  public BindingImpl<T> withScoping(Scoping scoping) {
+    return new LinkedProviderBindingImpl<T>(getSource(), getKey(), scoping, providerKey);
+  }
+
+  public BindingImpl<T> withKey(Key<T> key) {
+    return new LinkedProviderBindingImpl<T>(getSource(), key, getScoping(), providerKey);
+  }
+
+  public void applyTo(Binder binder) {
+    getScoping().applyTo(binder.withSource(getSource())
+        .bind(getKey()).toProvider(getProviderKey()));
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(ProviderKeyBinding.class)
+        .add("key", getKey())
+        .add("source", getSource())
+        .add("scope", getScoping())
+        .add("provider", providerKey)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if(obj instanceof LinkedProviderBindingImpl) {
+      LinkedProviderBindingImpl<?> o = (LinkedProviderBindingImpl<?>)obj;
+      return getKey().equals(o.getKey())
+        && getScoping().equals(o.getScoping())
+        && Objects.equal(providerKey, o.providerKey);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(getKey(), getScoping(), providerKey);
+  }
+}
diff --git a/core/src/com/google/inject/internal/ListenerBindingProcessor.java b/core/src/com/google/inject/internal/ListenerBindingProcessor.java
new file mode 100644
index 0000000..e8ebed2
--- /dev/null
+++ b/core/src/com/google/inject/internal/ListenerBindingProcessor.java
@@ -0,0 +1,42 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.inject.spi.ProvisionListenerBinding;
+import com.google.inject.spi.TypeListenerBinding;
+
+/**
+ * Handles {@code Binder#bindListener} commands.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class ListenerBindingProcessor extends AbstractProcessor {
+
+  ListenerBindingProcessor(Errors errors) {
+    super(errors);
+  }
+
+  @Override public Boolean visit(TypeListenerBinding binding) {
+    injector.state.addTypeListener(binding);
+    return true;
+  }
+  
+  @Override public Boolean visit(ProvisionListenerBinding binding) {
+    injector.state.addProvisionListener(binding);
+    return true;
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/LookupProcessor.java b/core/src/com/google/inject/internal/LookupProcessor.java
new file mode 100644
index 0000000..bf11b83
--- /dev/null
+++ b/core/src/com/google/inject/internal/LookupProcessor.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.MembersInjector;
+import com.google.inject.Provider;
+import com.google.inject.spi.MembersInjectorLookup;
+import com.google.inject.spi.ProviderLookup;
+
+/**
+ * Handles {@code Binder.getProvider} and {@code Binder.getMembersInjector(TypeLiteral)} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class LookupProcessor extends AbstractProcessor {
+
+  LookupProcessor(Errors errors) {
+    super(errors);
+  }
+
+  @Override public <T> Boolean visit(MembersInjectorLookup<T> lookup) {
+    try {
+      MembersInjector<T> membersInjector
+          = injector.membersInjectorStore.get(lookup.getType(), errors);
+      lookup.initializeDelegate(membersInjector);
+    } catch (ErrorsException e) {
+      errors.merge(e.getErrors()); // TODO: source
+    }
+
+    return true;
+  }
+
+  @Override public <T> Boolean visit(ProviderLookup<T> lookup) {
+    // ensure the provider can be created
+    try {
+      Provider<T> provider = injector.getProviderOrThrow(lookup.getDependency(), errors);
+      lookup.initializeDelegate(provider);
+    } catch (ErrorsException e) {
+      errors.merge(e.getErrors()); // TODO: source
+    }
+
+    return true;
+  }
+}
diff --git a/core/src/com/google/inject/internal/Lookups.java b/core/src/com/google/inject/internal/Lookups.java
new file mode 100644
index 0000000..2b32c7a
--- /dev/null
+++ b/core/src/com/google/inject/internal/Lookups.java
@@ -0,0 +1,35 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Accessors for providers and members injectors. The returned values will not be functional until
+ * the injector has been created.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+interface Lookups {
+
+  <T> Provider<T> getProvider(Key<T> key);
+
+  <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> type);
+}
diff --git a/core/src/com/google/inject/internal/MembersInjectorImpl.java b/core/src/com/google/inject/internal/MembersInjectorImpl.java
new file mode 100644
index 0000000..498b441
--- /dev/null
+++ b/core/src/com/google/inject/internal/MembersInjectorImpl.java
@@ -0,0 +1,165 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback;
+import com.google.inject.spi.InjectionListener;
+import com.google.inject.spi.InjectionPoint;
+
+/**
+ * Injects members of instances of a given type.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class MembersInjectorImpl<T> implements MembersInjector<T> {
+  private final TypeLiteral<T> typeLiteral;
+  private final InjectorImpl injector;
+  private final ImmutableList<SingleMemberInjector> memberInjectors;
+  private final ImmutableSet<MembersInjector<? super T>> userMembersInjectors;
+  private final ImmutableSet<InjectionListener<? super T>> injectionListeners;
+  /*if[AOP]*/
+  private final ImmutableList<MethodAspect> addedAspects;
+  /*end[AOP]*/
+
+  MembersInjectorImpl(InjectorImpl injector, TypeLiteral<T> typeLiteral,
+      EncounterImpl<T> encounter, ImmutableList<SingleMemberInjector> memberInjectors) {
+    this.injector = injector;
+    this.typeLiteral = typeLiteral;
+    this.memberInjectors = memberInjectors;
+    this.userMembersInjectors = encounter.getMembersInjectors();
+    this.injectionListeners = encounter.getInjectionListeners();
+    /*if[AOP]*/
+    this.addedAspects = encounter.getAspects();
+    /*end[AOP]*/
+  }
+
+  public ImmutableList<SingleMemberInjector> getMemberInjectors() {
+    return memberInjectors;
+  }
+
+  public void injectMembers(T instance) {
+    Errors errors = new Errors(typeLiteral);
+    try {
+      injectAndNotify(instance, errors, null, null, typeLiteral, false);
+    } catch (ErrorsException e) {
+      errors.merge(e.getErrors());
+    }
+
+    errors.throwProvisionExceptionIfErrorsExist();
+  }
+
+  void injectAndNotify(final T instance,
+      final Errors errors,
+      final Key<T> key, // possibly null!
+      final ProvisionListenerStackCallback<T> provisionCallback, // possibly null!
+      final Object source,
+      final boolean toolableOnly) throws ErrorsException {
+    if (instance == null) {
+      return;
+    }
+
+    injector.callInContext(new ContextualCallable<Void>() {
+      @Override
+      public Void call(final InternalContext context) throws ErrorsException {
+        context.pushState(key, source);
+        try {
+          if (provisionCallback != null && provisionCallback.hasListeners()) {
+            provisionCallback.provision(errors, context, new ProvisionCallback<T>() {
+              @Override public T call() {
+                injectMembers(instance, errors, context, toolableOnly);
+                return instance;
+              }
+            });
+          } else {
+            injectMembers(instance, errors, context, toolableOnly);
+          }
+        } finally {
+          context.popState();
+        }
+        return null;
+      }
+    });
+
+    // TODO: We *could* notify listeners too here,
+    // but it's not clear if we want to.  There's no way to know
+    // if a MembersInjector from the usersMemberInjector list wants
+    // toolable injections, so do we really want to notify
+    // about injection?  (We could take a strategy of only notifying
+    // if atleast one InjectionPoint was toolable, in which case
+    // the above callInContext could return 'true' if it injected
+    // anything.)
+    if(!toolableOnly) {
+      notifyListeners(instance, errors);
+    }
+  }
+
+  void notifyListeners(T instance, Errors errors) throws ErrorsException {
+    int numErrorsBefore = errors.size();
+    for (InjectionListener<? super T> injectionListener : injectionListeners) {
+      try {
+        injectionListener.afterInjection(instance);
+      } catch (RuntimeException e) {
+        errors.errorNotifyingInjectionListener(injectionListener, typeLiteral, e);
+      }
+    }
+    errors.throwIfNewErrors(numErrorsBefore);
+  }
+
+  void injectMembers(T t, Errors errors, InternalContext context, boolean toolableOnly) {
+    // optimization: use manual for/each to save allocating an iterator here
+    for (int i = 0, size = memberInjectors.size(); i < size; i++) {
+      SingleMemberInjector injector = memberInjectors.get(i);
+      if(!toolableOnly || injector.getInjectionPoint().isToolable()) {
+        injector.inject(errors, context, t);
+      }
+    }
+
+    // TODO: There's no way to know if a user's MembersInjector wants toolable injections.
+    if(!toolableOnly) {
+      for (MembersInjector<? super T> userMembersInjector : userMembersInjectors) {
+        try {
+          userMembersInjector.injectMembers(t);
+        } catch (RuntimeException e) {
+          errors.errorInUserInjector(userMembersInjector, typeLiteral, e);
+        }
+      }
+    }
+  }
+
+  @Override public String toString() {
+    return "MembersInjector<" + typeLiteral + ">";
+  }
+
+  public ImmutableSet<InjectionPoint> getInjectionPoints() {
+    ImmutableSet.Builder<InjectionPoint> builder = ImmutableSet.builder();
+    for (SingleMemberInjector memberInjector : memberInjectors) {
+      builder.add(memberInjector.getInjectionPoint());
+    }
+    return builder.build();
+  }
+
+  /*if[AOP]*/
+  public ImmutableList<MethodAspect> getAddedAspects() {
+    return addedAspects;
+  }
+  /*end[AOP]*/
+}
diff --git a/core/src/com/google/inject/internal/MembersInjectorStore.java b/core/src/com/google/inject/internal/MembersInjectorStore.java
new file mode 100644
index 0000000..8e2acdd
--- /dev/null
+++ b/core/src/com/google/inject/internal/MembersInjectorStore.java
@@ -0,0 +1,141 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.ConfigurationException;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.TypeListener;
+import com.google.inject.spi.TypeListenerBinding;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Members injectors by type.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class MembersInjectorStore {
+  private final InjectorImpl injector;
+  private final ImmutableList<TypeListenerBinding> typeListenerBindings;
+
+  private final FailableCache<TypeLiteral<?>, MembersInjectorImpl<?>> cache
+      = new FailableCache<TypeLiteral<?>, MembersInjectorImpl<?>>() {
+    @Override protected MembersInjectorImpl<?> create(TypeLiteral<?> type, Errors errors)
+        throws ErrorsException {
+      return createWithListeners(type, errors);
+    }
+  };
+
+  MembersInjectorStore(InjectorImpl injector,
+      List<TypeListenerBinding> typeListenerBindings) {
+    this.injector = injector;
+    this.typeListenerBindings = ImmutableList.copyOf(typeListenerBindings);
+  }
+
+  /**
+   * Returns true if any type listeners are installed. Other code may take shortcuts when there
+   * aren't any type listeners.
+   */
+  public boolean hasTypeListeners() {
+    return !typeListenerBindings.isEmpty();
+  }
+
+  /**
+   * Returns a new complete members injector with injection listeners registered.
+   */
+  @SuppressWarnings("unchecked") // the MembersInjector type always agrees with the passed type
+  public <T> MembersInjectorImpl<T> get(TypeLiteral<T> key, Errors errors) throws ErrorsException {
+    return (MembersInjectorImpl<T>) cache.get(key, errors);
+  }
+
+  /**
+   * Purges a type literal from the cache. Use this only if the type is not actually valid for
+   * binding and needs to be purged. (See issue 319 and
+   * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and
+   * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is
+   * necessary.)
+   * 
+   * Returns true if the type was stored in the cache, false otherwise.
+   */
+  boolean remove(TypeLiteral<?> type) {
+    return cache.remove(type);
+  }
+
+  /**
+   * Creates a new members injector and attaches both injection listeners and method aspects.
+   */
+  private <T> MembersInjectorImpl<T> createWithListeners(TypeLiteral<T> type, Errors errors)
+      throws ErrorsException {
+    int numErrorsBefore = errors.size();
+
+    Set<InjectionPoint> injectionPoints;
+    try {
+      injectionPoints = InjectionPoint.forInstanceMethodsAndFields(type);
+    } catch (ConfigurationException e) {
+      errors.merge(e.getErrorMessages());
+      injectionPoints = e.getPartialValue();
+    }
+    ImmutableList<SingleMemberInjector> injectors = getInjectors(injectionPoints, errors);
+    errors.throwIfNewErrors(numErrorsBefore);
+
+    EncounterImpl<T> encounter = new EncounterImpl<T>(errors, injector.lookups);
+    Set<TypeListener> alreadySeenListeners = Sets.newHashSet();
+    for (TypeListenerBinding binding : typeListenerBindings) {
+      TypeListener typeListener = binding.getListener();
+      if (!alreadySeenListeners.contains(typeListener) && binding.getTypeMatcher().matches(type)) {
+        alreadySeenListeners.add(typeListener);
+        try {
+          typeListener.hear(type, encounter);
+        } catch (RuntimeException e) {
+          errors.errorNotifyingTypeListener(binding, type, e);
+        }
+      }
+    }
+    encounter.invalidate();
+    errors.throwIfNewErrors(numErrorsBefore);
+
+    return new MembersInjectorImpl<T>(injector, type, encounter, injectors);
+  }
+
+  /**
+   * Returns the injectors for the specified injection points.
+   */
+  ImmutableList<SingleMemberInjector> getInjectors(
+      Set<InjectionPoint> injectionPoints, Errors errors) {
+    List<SingleMemberInjector> injectors = Lists.newArrayList();
+    for (InjectionPoint injectionPoint : injectionPoints) {
+      try {
+        Errors errorsForMember = injectionPoint.isOptional()
+            ? new Errors(injectionPoint)
+            : errors.withSource(injectionPoint);
+        SingleMemberInjector injector = injectionPoint.getMember() instanceof Field
+            ? new SingleFieldInjector(this.injector, injectionPoint, errorsForMember)
+            : new SingleMethodInjector(this.injector, injectionPoint, errorsForMember);
+        injectors.add(injector);
+      } catch (ErrorsException ignoredForNow) {
+        // ignored for now
+      }
+    }
+    return ImmutableList.copyOf(injectors);
+  }
+}
diff --git a/core/src/com/google/inject/internal/MessageProcessor.java b/core/src/com/google/inject/internal/MessageProcessor.java
new file mode 100644
index 0000000..d7c607b
--- /dev/null
+++ b/core/src/com/google/inject/internal/MessageProcessor.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.Guice;
+import com.google.inject.spi.Message;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Handles {@code Binder.addError} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class MessageProcessor extends AbstractProcessor {
+
+  private static final Logger logger = Logger.getLogger(Guice.class.getName());
+
+  MessageProcessor(Errors errors) {
+    super(errors);
+  }
+
+  @Override public Boolean visit(Message message) {
+    if (message.getCause() != null) {
+      String rootMessage = getRootMessage(message.getCause());
+      logger.log(Level.INFO,
+          "An exception was caught and reported. Message: " + rootMessage,
+          message.getCause());
+    }
+
+    errors.addMessage(message);
+    return true;
+  }
+
+  public static String getRootMessage(Throwable t) {
+    Throwable cause = t.getCause();
+    return cause == null ? t.toString() : getRootMessage(cause);
+  }
+}
diff --git a/core/src/com/google/inject/internal/MethodAspect.java b/core/src/com/google/inject/internal/MethodAspect.java
new file mode 100644
index 0000000..7bdf193
--- /dev/null
+++ b/core/src/com/google/inject/internal/MethodAspect.java
@@ -0,0 +1,70 @@
+/**
+ * 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 com.google.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.matcher.Matcher;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Ties a matcher to a method interceptor.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class MethodAspect {
+
+  private final Matcher<? super Class<?>> classMatcher;
+  private final Matcher<? super Method> methodMatcher;
+  private final List<MethodInterceptor> interceptors;
+
+  /**
+   * @param classMatcher matches classes the interceptor should apply to. For example: {@code
+   *     only(Runnable.class)}.
+   * @param methodMatcher matches methods the interceptor should apply to. For example: {@code
+   *     annotatedWith(Transactional.class)}.
+   * @param interceptors to apply
+   */
+  MethodAspect(Matcher<? super Class<?>> classMatcher,
+      Matcher<? super Method> methodMatcher, List<MethodInterceptor> interceptors) {
+    this.classMatcher = checkNotNull(classMatcher, "class matcher");
+    this.methodMatcher = checkNotNull(methodMatcher, "method matcher");
+    this.interceptors = checkNotNull(interceptors, "interceptors");
+  }
+
+  MethodAspect(Matcher<? super Class<?>> classMatcher,
+      Matcher<? super Method> methodMatcher, MethodInterceptor... interceptors) {
+    this(classMatcher, methodMatcher, Arrays.asList(interceptors));
+  }
+
+  boolean matches(Class<?> clazz) {
+    return classMatcher.matches(clazz);
+  }
+
+  boolean matches(Method method) {
+    return methodMatcher.matches(method);
+  }
+
+  List<MethodInterceptor> interceptors() {
+    return interceptors;
+  }
+}
diff --git a/core/src/com/google/inject/internal/ModuleAnnotatedMethodScannerProcessor.java b/core/src/com/google/inject/internal/ModuleAnnotatedMethodScannerProcessor.java
new file mode 100644
index 0000000..85c721d
--- /dev/null
+++ b/core/src/com/google/inject/internal/ModuleAnnotatedMethodScannerProcessor.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2015 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.inject.internal;
+
+import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding;
+
+/**
+ * Handles {@code Binder.scanModulesForAnnotatedMethods} commands.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+final class ModuleAnnotatedMethodScannerProcessor extends AbstractProcessor {
+
+  ModuleAnnotatedMethodScannerProcessor(Errors errors) {
+    super(errors);
+  }
+
+  @Override public Boolean visit(ModuleAnnotatedMethodScannerBinding command) {
+    injector.state.addScanner(command);
+    return true;
+  }
+}
diff --git a/core/src/com/google/inject/internal/MoreTypes.java b/core/src/com/google/inject/internal/MoreTypes.java
new file mode 100644
index 0000000..bdf6029
--- /dev/null
+++ b/core/src/com/google/inject/internal/MoreTypes.java
@@ -0,0 +1,551 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.util.Types;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+/**
+ * Static methods for working with types that we aren't publishing in the
+ * public {@code Types} API.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class MoreTypes {
+
+  public static final Type[] EMPTY_TYPE_ARRAY = new Type[] {};
+
+  private MoreTypes() {}
+
+  private static final Map<TypeLiteral<?>, TypeLiteral<?>> PRIMITIVE_TO_WRAPPER
+      = new ImmutableMap.Builder<TypeLiteral<?>, TypeLiteral<?>>()
+          .put(TypeLiteral.get(boolean.class), TypeLiteral.get(Boolean.class))
+          .put(TypeLiteral.get(byte.class), TypeLiteral.get(Byte.class))
+          .put(TypeLiteral.get(short.class), TypeLiteral.get(Short.class))
+          .put(TypeLiteral.get(int.class), TypeLiteral.get(Integer.class))
+          .put(TypeLiteral.get(long.class), TypeLiteral.get(Long.class))
+          .put(TypeLiteral.get(float.class), TypeLiteral.get(Float.class))
+          .put(TypeLiteral.get(double.class), TypeLiteral.get(Double.class))
+          .put(TypeLiteral.get(char.class), TypeLiteral.get(Character.class))
+          .put(TypeLiteral.get(void.class), TypeLiteral.get(Void.class))
+          .build();
+
+  /**
+   * Returns a key that doesn't hold any references to parent classes.
+   * This is necessary for anonymous keys, so ensure we don't hold a ref
+   * to the containing module (or class) forever.
+   */
+  public static <T> Key<T> canonicalizeKey(Key<T> key) {
+    // If we know this isn't a subclass, return as-is.
+    // Otherwise, recreate the key to avoid the subclass 
+    if (key.getClass() == Key.class) {
+      return key;
+    } else if (key.getAnnotation() != null) {
+      return Key.get(key.getTypeLiteral(), key.getAnnotation());
+    } else if (key.getAnnotationType() != null) {
+      return Key.get(key.getTypeLiteral(), key.getAnnotationType());
+    } else {
+      return Key.get(key.getTypeLiteral());
+    }
+  }
+
+  /**
+   * Returns an type that's appropriate for use in a key.
+   *
+   * <p>If the raw type of {@code typeLiteral} is a {@code javax.inject.Provider}, this returns a
+   * {@code com.google.inject.Provider} with the same type parameters.
+   *
+   * <p>If the type is a primitive, the corresponding wrapper type will be returned.
+   *
+   * @throws ConfigurationException if {@code type} contains a type variable
+   */
+  public static <T> TypeLiteral<T> canonicalizeForKey(TypeLiteral<T> typeLiteral) {
+    Type type = typeLiteral.getType();
+    if (!isFullySpecified(type)) {
+      Errors errors = new Errors().keyNotFullySpecified(typeLiteral);
+      throw new ConfigurationException(errors.getMessages());
+    }
+
+    if (typeLiteral.getRawType() == javax.inject.Provider.class) {
+      ParameterizedType parameterizedType = (ParameterizedType) type;
+
+      // the following casts are generally unsafe, but com.google.inject.Provider extends
+      // javax.inject.Provider and is covariant
+      @SuppressWarnings("unchecked")
+      TypeLiteral<T> guiceProviderType = (TypeLiteral<T>) TypeLiteral.get(
+          Types.providerOf(parameterizedType.getActualTypeArguments()[0]));
+      return guiceProviderType;
+    }
+
+    @SuppressWarnings("unchecked")
+    TypeLiteral<T> wrappedPrimitives = (TypeLiteral<T>) PRIMITIVE_TO_WRAPPER.get(typeLiteral);
+    if (wrappedPrimitives != null) {
+      return wrappedPrimitives;
+    }
+
+    // If we know this isn't a subclass, return as-is.
+    if (typeLiteral.getClass() == TypeLiteral.class) {
+      return typeLiteral;
+    }
+
+    // recreate the TypeLiteral to avoid anonymous TypeLiterals from holding refs to their
+    // surrounding classes.
+    @SuppressWarnings("unchecked")
+    TypeLiteral<T> recreated = (TypeLiteral<T>) TypeLiteral.get(typeLiteral.getType());
+    return recreated;
+  }
+
+  /**
+   * Returns true if {@code type} is free from type variables.
+   */
+  private static boolean isFullySpecified(Type type) {
+    if (type instanceof Class) {
+      return true;
+
+    } else if (type instanceof CompositeType) {
+      return ((CompositeType) type).isFullySpecified();
+
+    } else if (type instanceof TypeVariable){
+      return false;
+
+    } else {
+      return ((CompositeType) canonicalize(type)).isFullySpecified();
+    }
+  }
+
+  /**
+   * Returns a type that is functionally equal but not necessarily equal
+   * according to {@link Object#equals(Object) Object.equals()}. The returned
+   * type is {@link Serializable}.
+   */
+  public static Type canonicalize(Type type) {
+    if (type instanceof Class) {
+      Class<?> c = (Class<?>) type;
+      return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;
+
+    } else if (type instanceof CompositeType) {
+      return type;
+
+    } else if (type instanceof ParameterizedType) {
+      ParameterizedType p = (ParameterizedType) type;
+      return new ParameterizedTypeImpl(p.getOwnerType(),
+          p.getRawType(), p.getActualTypeArguments());
+
+    } else if (type instanceof GenericArrayType) {
+      GenericArrayType g = (GenericArrayType) type;
+      return new GenericArrayTypeImpl(g.getGenericComponentType());
+
+    } else if (type instanceof WildcardType) {
+      WildcardType w = (WildcardType) type;
+      return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());
+
+    } else {
+      // type is either serializable as-is or unsupported
+      return type;
+    }
+  }
+
+  public static Class<?> getRawType(Type type) {
+    if (type instanceof Class<?>) {
+      // type is a normal class.
+      return (Class<?>) type;
+
+    } else if (type instanceof ParameterizedType) {
+      ParameterizedType parameterizedType = (ParameterizedType) type;
+
+      // I'm not exactly sure why getRawType() returns Type instead of Class.
+      // Neal isn't either but suspects some pathological case related
+      // to nested classes exists.
+      Type rawType = parameterizedType.getRawType();
+      checkArgument(rawType instanceof Class,
+          "Expected a Class, but <%s> is of type %s", type, type.getClass().getName());
+      return (Class<?>) rawType;
+
+    } else if (type instanceof GenericArrayType) {
+      Type componentType = ((GenericArrayType)type).getGenericComponentType();
+      return Array.newInstance(getRawType(componentType), 0).getClass();
+
+    } else if (type instanceof TypeVariable) {
+      // we could use the variable's bounds, but that'll won't work if there are multiple.
+      // having a raw type that's more general than necessary is okay  
+      return Object.class;
+
+    } else {
+      throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+          + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
+    }
+  }
+
+  /**
+   * Returns true if {@code a} and {@code b} are equal.
+   */
+  public static boolean equals(Type a, Type b) {
+    if (a == b) {
+      // also handles (a == null && b == null)
+      return true;
+
+    } else if (a instanceof Class) {
+      // Class already specifies equals().
+      return a.equals(b);
+
+    } else if (a instanceof ParameterizedType) {
+      if (!(b instanceof ParameterizedType)) {
+        return false;
+      }
+
+      // TODO: save a .clone() call
+      ParameterizedType pa = (ParameterizedType) a;
+      ParameterizedType pb = (ParameterizedType) b;
+      return Objects.equal(pa.getOwnerType(), pb.getOwnerType())
+          && pa.getRawType().equals(pb.getRawType())
+          && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments());
+
+    } else if (a instanceof GenericArrayType) {
+      if (!(b instanceof GenericArrayType)) {
+        return false;
+      }
+
+      GenericArrayType ga = (GenericArrayType) a;
+      GenericArrayType gb = (GenericArrayType) b;
+      return equals(ga.getGenericComponentType(), gb.getGenericComponentType());
+
+    } else if (a instanceof WildcardType) {
+      if (!(b instanceof WildcardType)) {
+        return false;
+      }
+
+      WildcardType wa = (WildcardType) a;
+      WildcardType wb = (WildcardType) b;
+      return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds())
+          && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds());
+
+    } else if (a instanceof TypeVariable) {
+      if (!(b instanceof TypeVariable)) {
+        return false;
+      }
+      TypeVariable<?> va = (TypeVariable) a;
+      TypeVariable<?> vb = (TypeVariable) b;
+      return va.getGenericDeclaration().equals(vb.getGenericDeclaration())
+          && va.getName().equals(vb.getName());
+
+    } else {
+      // This isn't a type we support. Could be a generic array type, wildcard type, etc.
+      return false;
+    }
+  }
+
+  private static int hashCodeOrZero(Object o) {
+    return o != null ? o.hashCode() : 0;
+  }
+
+  public static String typeToString(Type type) {
+    return type instanceof Class ? ((Class) type).getName() : type.toString();
+  }
+
+  /**
+   * Returns the generic supertype for {@code type}. For example, given a class {@code IntegerSet},
+   * the result for when supertype is {@code Set.class} is {@code Set<Integer>} and the result
+   * when the supertype is {@code Collection.class} is {@code Collection<Integer>}.
+   */
+  public static Type getGenericSupertype(Type type, Class<?> rawType, Class<?> toResolve) {
+    if (toResolve == rawType) {
+      return type;
+    }
+
+    // we skip searching through interfaces if unknown is an interface
+    if (toResolve.isInterface()) {
+      Class[] interfaces = rawType.getInterfaces();
+      for (int i = 0, length = interfaces.length; i < length; i++) {
+        if (interfaces[i] == toResolve) {
+          return rawType.getGenericInterfaces()[i];
+        } else if (toResolve.isAssignableFrom(interfaces[i])) {
+          return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve);
+        }
+      }
+    }
+
+    // check our supertypes
+    if (!rawType.isInterface()) {
+      while (rawType != Object.class) {
+        Class<?> rawSupertype = rawType.getSuperclass();
+        if (rawSupertype == toResolve) {
+          return rawType.getGenericSuperclass();
+        } else if (toResolve.isAssignableFrom(rawSupertype)) {
+          return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve);
+        }
+        rawType = rawSupertype;
+      }
+    }
+
+    // we can't resolve this further
+    return toResolve;
+  }
+
+  public static Type resolveTypeVariable(Type type, Class<?> rawType, TypeVariable unknown) {
+    Class<?> declaredByRaw = declaringClassOf(unknown);
+
+    // we can't reduce this further
+    if (declaredByRaw == null) {
+      return unknown;
+    }
+
+    Type declaredBy = getGenericSupertype(type, rawType, declaredByRaw);
+    if (declaredBy instanceof ParameterizedType) {
+      int index = indexOf(declaredByRaw.getTypeParameters(), unknown);
+      return ((ParameterizedType) declaredBy).getActualTypeArguments()[index];
+    }
+
+    return unknown;
+  }
+
+  private static int indexOf(Object[] array, Object toFind) {
+    for (int i = 0; i < array.length; i++) {
+      if (toFind.equals(array[i])) {
+        return i;
+      }
+    }
+    throw new NoSuchElementException();
+  }
+
+  /**
+   * Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by
+   * a class.
+   */
+  private static Class<?> declaringClassOf(TypeVariable typeVariable) {
+    GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
+    return genericDeclaration instanceof Class
+        ? (Class<?>) genericDeclaration
+        : null;
+  }
+
+  public static class ParameterizedTypeImpl
+      implements ParameterizedType, Serializable, CompositeType {
+    private final Type ownerType;
+    private final Type rawType;
+    private final Type[] typeArguments;
+
+    public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) {
+      // require an owner type if the raw type needs it
+      ensureOwnerType(ownerType, rawType);
+
+      this.ownerType = ownerType == null ? null : canonicalize(ownerType);
+      this.rawType = canonicalize(rawType);
+      this.typeArguments = typeArguments.clone();
+      for (int t = 0; t < this.typeArguments.length; t++) {
+        checkNotNull(this.typeArguments[t], "type parameter");
+        checkNotPrimitive(this.typeArguments[t], "type parameters");
+        this.typeArguments[t] = canonicalize(this.typeArguments[t]);
+      }
+    }
+
+    public Type[] getActualTypeArguments() {
+      return typeArguments.clone();
+    }
+
+    public Type getRawType() {
+      return rawType;
+    }
+
+    public Type getOwnerType() {
+      return ownerType;
+    }
+
+    public boolean isFullySpecified() {
+      if (ownerType != null && !MoreTypes.isFullySpecified(ownerType)) {
+        return false;
+      }
+
+      if (!MoreTypes.isFullySpecified(rawType)) {
+        return false;
+      }
+
+      for (Type type : typeArguments) {
+        if (!MoreTypes.isFullySpecified(type)) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof ParameterizedType
+          && MoreTypes.equals(this, (ParameterizedType) other);
+    }
+
+    @Override public int hashCode() {
+      return Arrays.hashCode(typeArguments)
+          ^ rawType.hashCode()
+          ^ hashCodeOrZero(ownerType);
+    }
+
+    @Override public String toString() {
+      StringBuilder stringBuilder = new StringBuilder(30 * (typeArguments.length + 1));
+      stringBuilder.append(typeToString(rawType));
+
+      if (typeArguments.length == 0) {
+        return stringBuilder.toString();
+      }
+
+      stringBuilder.append("<").append(typeToString(typeArguments[0]));
+      for (int i = 1; i < typeArguments.length; i++) {
+        stringBuilder.append(", ").append(typeToString(typeArguments[i]));
+      }
+      return stringBuilder.append(">").toString();
+    }
+
+    private static void ensureOwnerType(Type ownerType, Type rawType) {
+      if (rawType instanceof Class<?>) {
+        Class rawTypeAsClass = (Class) rawType;
+        checkArgument(ownerType != null || rawTypeAsClass.getEnclosingClass() == null,
+            "No owner type for enclosed %s", rawType);
+        checkArgument(ownerType == null || rawTypeAsClass.getEnclosingClass() != null,
+            "Owner type for unenclosed %s", rawType);
+      }
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  public static class GenericArrayTypeImpl
+      implements GenericArrayType, Serializable, CompositeType {
+    private final Type componentType;
+
+    public GenericArrayTypeImpl(Type componentType) {
+      this.componentType = canonicalize(componentType);
+    }
+
+    public Type getGenericComponentType() {
+      return componentType;
+    }
+
+    public boolean isFullySpecified() {
+      return MoreTypes.isFullySpecified(componentType);
+    }
+
+    @Override public boolean equals(Object o) {
+      return o instanceof GenericArrayType
+          && MoreTypes.equals(this, (GenericArrayType) o);
+    }
+
+    @Override public int hashCode() {
+      return componentType.hashCode();
+    }
+
+    @Override public String toString() {
+      return typeToString(componentType) + "[]";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * The WildcardType interface supports multiple upper bounds and multiple
+   * lower bounds. We only support what the Java 6 language needs - at most one
+   * bound. If a lower bound is set, the upper bound must be Object.class.
+   */
+  public static class WildcardTypeImpl implements WildcardType, Serializable, CompositeType {
+    private final Type upperBound;
+    private final Type lowerBound;
+
+    public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
+      checkArgument(lowerBounds.length <= 1, "Must have at most one lower bound.");
+      checkArgument(upperBounds.length == 1, "Must have exactly one upper bound.");
+
+      if (lowerBounds.length == 1) {
+        checkNotNull(lowerBounds[0], "lowerBound");
+        checkNotPrimitive(lowerBounds[0], "wildcard bounds");
+        checkArgument(upperBounds[0] == Object.class, "bounded both ways");
+        this.lowerBound = canonicalize(lowerBounds[0]);
+        this.upperBound = Object.class;
+
+      } else {
+        checkNotNull(upperBounds[0], "upperBound");
+        checkNotPrimitive(upperBounds[0], "wildcard bounds");
+        this.lowerBound = null;
+        this.upperBound = canonicalize(upperBounds[0]);
+      }
+    }
+
+    public Type[] getUpperBounds() {
+      return new Type[] { upperBound };
+    }
+
+    public Type[] getLowerBounds() {
+      return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY;
+    }
+
+    public boolean isFullySpecified() {
+      return MoreTypes.isFullySpecified(upperBound)
+          && (lowerBound == null || MoreTypes.isFullySpecified(lowerBound));
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof WildcardType
+          && MoreTypes.equals(this, (WildcardType) other);
+    }
+
+    @Override public int hashCode() {
+      // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds());  
+      return (lowerBound != null ? 31 + lowerBound.hashCode() : 1)
+          ^ (31 + upperBound.hashCode());
+    }
+
+    @Override public String toString() {
+      if (lowerBound != null) {
+        return "? super " + typeToString(lowerBound);
+      } else if (upperBound == Object.class) {
+        return "?";
+      } else {
+        return "? extends " + typeToString(upperBound);
+      }
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  private static void checkNotPrimitive(Type type, String use) {
+    checkArgument(!(type instanceof Class<?>) || !((Class) type).isPrimitive(),
+        "Primitive types are not allowed in %s: %s", use, type);
+  }
+
+  /** A type formed from other types, such as arrays, parameterized types or wildcard types */
+  private interface CompositeType {
+    /** Returns true if there are no type variables in this type. */
+    boolean isFullySpecified();
+  }
+}
diff --git a/core/src/com/google/inject/internal/Nullability.java b/core/src/com/google/inject/internal/Nullability.java
new file mode 100644
index 0000000..76f7e76
--- /dev/null
+++ b/core/src/com/google/inject/internal/Nullability.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2010 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.inject.internal;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Whether a member supports null values injected.
+ *
+ * <p>Support for {@code Nullable} annotations in Guice is loose.
+ * Any annotation type whose simplename is "Nullable" is sufficient to indicate
+ * support for null values injected.
+ *
+ * <p>This allows support for JSR-305's
+ * <a href="http://groups.google.com/group/jsr-305/web/proposed-annotations">
+ * javax.annotation.meta.Nullable</a> annotation and IntelliJ IDEA's
+ * <a href="http://www.jetbrains.com/idea/documentation/howto.html">
+ * org.jetbrains.annotations.Nullable</a>.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class Nullability {
+  private Nullability() {}
+
+  public static boolean allowsNull(Annotation[] annotations) {
+    for(Annotation a : annotations) {
+      Class<? extends Annotation> type = a.annotationType();
+      if ("Nullable".equals(type.getSimpleName())) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/core/src/com/google/inject/internal/PrivateElementProcessor.java b/core/src/com/google/inject/internal/PrivateElementProcessor.java
new file mode 100644
index 0000000..4a641a9
--- /dev/null
+++ b/core/src/com/google/inject/internal/PrivateElementProcessor.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.collect.Lists;
+import com.google.inject.spi.PrivateElements;
+
+import java.util.List;
+
+/**
+ * Handles {@code Binder.newPrivateBinder()} elements.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class PrivateElementProcessor extends AbstractProcessor {
+
+  private final List<InjectorShell.Builder> injectorShellBuilders = Lists.newArrayList();
+
+  PrivateElementProcessor(Errors errors) {
+    super(errors);
+  }
+
+  @Override public Boolean visit(PrivateElements privateElements) {
+    InjectorShell.Builder builder = new InjectorShell.Builder()
+        .parent(injector)
+        .privateElements(privateElements);
+    injectorShellBuilders.add(builder);
+    return true;
+  }
+
+  public List<InjectorShell.Builder> getInjectorShellBuilders() {
+    return injectorShellBuilders;
+  }
+}
diff --git a/core/src/com/google/inject/internal/PrivateElementsImpl.java b/core/src/com/google/inject/internal/PrivateElementsImpl.java
new file mode 100644
index 0000000..6a3d915
--- /dev/null
+++ b/core/src/com/google/inject/internal/PrivateElementsImpl.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Binder;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.PrivateBinder;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.ElementVisitor;
+import com.google.inject.spi.PrivateElements;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public final class PrivateElementsImpl implements PrivateElements {
+
+  /*
+   * This class acts as both a value object and as a builder. When getElements() is called, an
+   * immutable collection of elements is constructed and the original mutable list is nulled out.
+   * Similarly, the exposed keys are made immutable on access.
+   */
+
+  private final Object source;
+
+  private List<Element> elementsMutable = Lists.newArrayList();
+  private List<ExposureBuilder<?>> exposureBuilders = Lists.newArrayList();
+
+  /** lazily instantiated */
+  private ImmutableList<Element> elements;
+
+  /** lazily instantiated */
+  private ImmutableMap<Key<?>, Object> exposedKeysToSources;
+  private Injector injector;
+
+  public PrivateElementsImpl(Object source) {
+    this.source = checkNotNull(source, "source");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public List<Element> getElements() {
+    if (elements == null) {
+      elements = ImmutableList.copyOf(elementsMutable);
+      elementsMutable = null;
+    }
+
+    return elements;
+  }
+
+  public Injector getInjector() {
+    return injector;
+  }
+
+  public void initInjector(Injector injector) {
+    checkState(this.injector == null, "injector already initialized");
+    this.injector = checkNotNull(injector, "injector");
+  }
+
+  public Set<Key<?>> getExposedKeys() {
+    if (exposedKeysToSources == null) {
+      Map<Key<?>, Object> exposedKeysToSourcesMutable = Maps.newLinkedHashMap();
+      for (ExposureBuilder<?> exposureBuilder : exposureBuilders) {
+        exposedKeysToSourcesMutable.put(exposureBuilder.getKey(), exposureBuilder.getSource());
+      }
+      exposedKeysToSources = ImmutableMap.copyOf(exposedKeysToSourcesMutable);
+      exposureBuilders = null;
+    }
+
+    return exposedKeysToSources.keySet();
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  public List<Element> getElementsMutable() {
+    return elementsMutable;
+  }
+
+  public void addExposureBuilder(ExposureBuilder<?> exposureBuilder) {
+    exposureBuilders.add(exposureBuilder);
+  }
+
+  public void applyTo(Binder binder) {
+    PrivateBinder privateBinder = binder.withSource(source).newPrivateBinder();
+
+    for (Element element : getElements()) {
+      element.applyTo(privateBinder);
+    }
+
+    getExposedKeys(); // ensure exposedKeysToSources is populated
+    for (Map.Entry<Key<?>, Object> entry : exposedKeysToSources.entrySet()) {
+      privateBinder.withSource(entry.getValue()).expose(entry.getKey());
+    }
+  }
+
+  public Object getExposedSource(Key<?> key) {
+    getExposedKeys(); // ensure exposedKeysToSources is populated
+    Object source = exposedKeysToSources.get(key);
+    checkArgument(source != null, "%s not exposed by %s.", key, this);
+    return source;
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(PrivateElements.class)
+        .add("exposedKeys", getExposedKeys())
+        .add("source", getSource())
+        .toString();
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProcessedBindingData.java b/core/src/com/google/inject/internal/ProcessedBindingData.java
new file mode 100644
index 0000000..8cd2602
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProcessedBindingData.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.internal;
+
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+/**
+ * Keeps track of creation listeners & uninitialized bindings,
+ * so they can be processed after bindings are recorded.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+class ProcessedBindingData {
+  
+  private final List<CreationListener> creationListeners = Lists.newArrayList();
+  private final List<Runnable> uninitializedBindings = Lists.newArrayList();
+  
+  void addCreationListener(CreationListener listener) {
+    creationListeners.add(listener);
+  }
+  
+  void addUninitializedBinding(Runnable runnable) {
+    uninitializedBindings.add(runnable);
+  }
+  
+  void initializeBindings() {
+    for (Runnable initializer : uninitializedBindings) {
+      initializer.run();
+    }
+  }
+
+  void runCreationListeners(Errors errors) {
+    for (CreationListener creationListener : creationListeners) {
+      creationListener.notify(errors);
+    }
+  }
+
+}
diff --git a/core/src/com/google/inject/internal/ProvidedByInternalFactory.java b/core/src/com/google/inject/internal/ProvidedByInternalFactory.java
new file mode 100644
index 0000000..1591c50
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProvidedByInternalFactory.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.google.inject.internal;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.inject.Key;
+import com.google.inject.ProvidedBy;
+import com.google.inject.Provider;
+import com.google.inject.internal.InjectorImpl.JitLimitation;
+import com.google.inject.spi.Dependency;
+
+/**
+ * An {@link InternalFactory} for {@literal @}{@link ProvidedBy} bindings.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+class ProvidedByInternalFactory<T> extends ProviderInternalFactory<T>
+    implements DelayedInitialize {
+  
+  private final Class<?> rawType;
+  private final Class<? extends Provider<?>> providerType;
+  private final Key<? extends Provider<T>> providerKey;
+  private BindingImpl<? extends Provider<T>> providerBinding;
+  private ProvisionListenerStackCallback<T> provisionCallback;
+  
+  ProvidedByInternalFactory(
+      Class<?> rawType,
+      Class<? extends Provider<?>> providerType,
+      Key<? extends Provider<T>> providerKey) {
+    super(providerKey);
+    this.rawType = rawType;
+    this.providerType = providerType; 
+    this.providerKey = providerKey;
+  }
+  
+  void setProvisionListenerCallback(ProvisionListenerStackCallback<T> listener) {
+    provisionCallback = listener;
+  }
+  
+  public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
+    providerBinding =
+        injector.getBindingOrThrow(providerKey, errors, JitLimitation.NEW_OR_EXISTING_JIT);
+  }
+
+  public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked)
+      throws ErrorsException {
+    checkState(providerBinding != null, "not initialized");
+    
+    context.pushState(providerKey, providerBinding.getSource());
+    try {
+      errors = errors.withSource(providerKey);
+      Provider<? extends T> provider = providerBinding.getInternalFactory().get(
+          errors, context, dependency, true);
+      return circularGet(provider, errors, context, dependency, provisionCallback);
+    } finally {
+      context.popState();
+    }
+  }
+  
+  @Override
+  protected T provision(javax.inject.Provider<? extends T> provider, Errors errors,
+      Dependency<?> dependency, ConstructionContext<T> constructionContext)
+      throws ErrorsException {
+    try {
+      Object o = super.provision(provider, errors, dependency, constructionContext);
+      if (o != null && !rawType.isInstance(o)) {
+        throw errors.subtypeNotProvided(providerType, rawType).toException();
+      }
+      @SuppressWarnings("unchecked") // protected by isInstance() check above
+      T t = (T) o;
+      return t;
+    } catch (RuntimeException e) {
+      throw errors.errorInProvider(e).toException();
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProviderInstanceBindingImpl.java b/core/src/com/google/inject/internal/ProviderInstanceBindingImpl.java
new file mode 100644
index 0000000..f254b41
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProviderInstanceBindingImpl.java
@@ -0,0 +1,125 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+import com.google.inject.util.Providers;
+
+import java.util.Set;
+
+final class ProviderInstanceBindingImpl<T> extends BindingImpl<T>
+    implements ProviderInstanceBinding<T> {
+
+  final javax.inject.Provider<? extends T> providerInstance;
+  final ImmutableSet<InjectionPoint> injectionPoints;
+
+  public ProviderInstanceBindingImpl(InjectorImpl injector, Key<T> key,
+      Object source, InternalFactory<? extends T> internalFactory, Scoping scoping,
+      javax.inject.Provider<? extends T> providerInstance,
+      Set<InjectionPoint> injectionPoints) {
+    super(injector, key, source, internalFactory, scoping);
+    this.providerInstance = providerInstance;
+    this.injectionPoints = ImmutableSet.copyOf(injectionPoints);
+  }
+
+  public ProviderInstanceBindingImpl(Object source, Key<T> key, Scoping scoping,
+      Set<InjectionPoint> injectionPoints, javax.inject.Provider<? extends T> providerInstance) {
+    super(source, key, scoping);
+    this.injectionPoints = ImmutableSet.copyOf(injectionPoints);
+    this.providerInstance = providerInstance;
+  }
+
+  @SuppressWarnings("unchecked") // the extension type is always consistent with the provider type
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
+    if(providerInstance instanceof ProviderWithExtensionVisitor) {
+      return ((ProviderWithExtensionVisitor<? extends T>) providerInstance)
+          .acceptExtensionVisitor(visitor, this);
+    } else {
+      return visitor.visit(this);
+    }
+  }
+
+  public Provider<? extends T> getProviderInstance() {
+    return Providers.guicify(providerInstance);
+  }
+  
+  public javax.inject.Provider<? extends T> getUserSuppliedProvider() {
+    return providerInstance;
+  }
+
+  public Set<InjectionPoint> getInjectionPoints() {
+    return injectionPoints;
+  }
+
+  public Set<Dependency<?>> getDependencies() {
+    return providerInstance instanceof HasDependencies
+        ? ImmutableSet.copyOf(((HasDependencies) providerInstance).getDependencies())
+        : Dependency.forInjectionPoints(injectionPoints);
+  }
+
+  public BindingImpl<T> withScoping(Scoping scoping) {
+    return new ProviderInstanceBindingImpl<T>(
+        getSource(), getKey(), scoping, injectionPoints, providerInstance);
+  }
+
+  public BindingImpl<T> withKey(Key<T> key) {
+    return new ProviderInstanceBindingImpl<T>(
+        getSource(), key, getScoping(), injectionPoints, providerInstance);
+  }
+
+  public void applyTo(Binder binder) {
+    getScoping().applyTo(
+        binder.withSource(getSource()).bind(getKey()).toProvider(getUserSuppliedProvider()));
+  }
+
+  @Override
+  public String toString() {
+    return Objects.toStringHelper(ProviderInstanceBinding.class)
+        .add("key", getKey())
+        .add("source", getSource())
+        .add("scope", getScoping())
+        .add("provider", providerInstance)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if(obj instanceof ProviderInstanceBindingImpl) {
+      ProviderInstanceBindingImpl<?> o = (ProviderInstanceBindingImpl<?>)obj;
+      return getKey().equals(o.getKey())
+        && getScoping().equals(o.getScoping())
+        && Objects.equal(providerInstance, o.providerInstance);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(getKey(), getScoping());
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProviderInternalFactory.java b/core/src/com/google/inject/internal/ProviderInternalFactory.java
new file mode 100644
index 0000000..8574535
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProviderInternalFactory.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.google.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback;
+import com.google.inject.spi.Dependency;
+
+import javax.inject.Provider;
+
+/**
+ * Base class for InternalFactories that are used by Providers, to handle
+ * circular dependencies.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+abstract class ProviderInternalFactory<T> implements InternalFactory<T> {
+  
+  protected final Object source;
+  
+  ProviderInternalFactory(Object source) {
+    this.source = checkNotNull(source, "source");
+  }
+  
+  protected T circularGet(final Provider<? extends T> provider, final Errors errors,
+      InternalContext context, final Dependency<?> dependency,
+      ProvisionListenerStackCallback<T> provisionCallback)
+      throws ErrorsException {    
+    final ConstructionContext<T> constructionContext = context.getConstructionContext(this);
+
+    // We have a circular reference between constructors. Return a proxy.
+    if (constructionContext.isConstructing()) {
+        Class<?> expectedType = dependency.getKey().getTypeLiteral().getRawType();
+        // TODO: if we can't proxy this object, can we proxy the other object?
+        @SuppressWarnings("unchecked")
+        T proxyType = (T) constructionContext.createProxy(
+            errors, context.getInjectorOptions(), expectedType);
+        return proxyType;
+    }
+
+    // Optimization: Don't go through the callback stack if no one's listening.
+    constructionContext.startConstruction();
+    try {
+      if (!provisionCallback.hasListeners()) {
+        return provision(provider, errors, dependency, constructionContext);
+      } else {
+        return provisionCallback.provision(errors, context, new ProvisionCallback<T>() {
+          public T call() throws ErrorsException {
+            return provision(provider, errors, dependency, constructionContext);
+          }
+        });
+      }
+    } finally {
+      constructionContext.removeCurrentReference();
+      constructionContext.finishConstruction();
+    }
+  }
+
+  /**
+   * Provisions a new instance. Subclasses should override this to catch
+   * exceptions & rethrow as ErrorsExceptions.
+   */
+  protected T provision(Provider<? extends T> provider, Errors errors, Dependency<?> dependency,
+      ConstructionContext<T> constructionContext) throws ErrorsException {
+    T t = errors.checkForNull(provider.get(), source, dependency);
+    constructionContext.setProxyDelegates(t);
+    return t;
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProviderMethod.java b/core/src/com/google/inject/internal/ProviderMethod.java
new file mode 100644
index 0000000..beaf406
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProviderMethod.java
@@ -0,0 +1,302 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Exposed;
+import com.google.inject.Key;
+import com.google.inject.PrivateBinder;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.internal.BytecodeGen.Visibility;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+import com.google.inject.spi.ProvidesMethodBinding;
+import com.google.inject.spi.ProvidesMethodTargetVisitor;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A provider that invokes a method and returns its result.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public abstract class ProviderMethod<T> implements ProviderWithExtensionVisitor<T>, HasDependencies,
+    ProvidesMethodBinding<T> {
+
+  /**
+   * Creates a {@link ProviderMethod}.
+   *
+   * <p>Unless {@code skipFastClassGeneration} is set, this will use
+   * {@link net.sf.cglib.reflect.FastClass} to invoke the actual method, since it is significantly
+   * faster. However, this will fail if the method is {@code private} or {@code protected}, since
+   * fastclass is subject to java access policies.
+   */
+  static <T> ProviderMethod<T> create(Key<T> key, Method method, Object instance,
+      ImmutableSet<Dependency<?>> dependencies, List<Provider<?>> parameterProviders,
+      Class<? extends Annotation> scopeAnnotation, boolean skipFastClassGeneration,
+      Annotation annotation) {
+    int modifiers = method.getModifiers();
+    /*if[AOP]*/
+    if (!skipFastClassGeneration && !Modifier.isPrivate(modifiers)
+        && !Modifier.isProtected(modifiers)) {
+      try {
+        // We use an index instead of FastMethod to save a stack frame.
+        return new FastClassProviderMethod<T>(key,
+            method,
+            instance,
+            dependencies,
+            parameterProviders,
+            scopeAnnotation,
+            annotation);
+      } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */}
+    }
+    /*end[AOP]*/
+
+    if (!Modifier.isPublic(modifiers) ||
+        !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
+      method.setAccessible(true);
+    }
+
+    return new ReflectionProviderMethod<T>(key,
+        method,
+        instance,
+        dependencies,
+        parameterProviders,
+        scopeAnnotation,
+        annotation);
+  }
+
+  protected final Object instance;
+  protected final Method method;
+
+  private final Key<T> key;
+  private final Class<? extends Annotation> scopeAnnotation;
+  private final ImmutableSet<Dependency<?>> dependencies;
+  private final List<Provider<?>> parameterProviders;
+  private final boolean exposed;
+  private final Annotation annotation;
+
+  /**
+   * @param method the method to invoke. It's return type must be the same type as {@code key}.
+   */
+  private ProviderMethod(Key<T> key, Method method, Object instance,
+      ImmutableSet<Dependency<?>> dependencies, List<Provider<?>> parameterProviders,
+      Class<? extends Annotation> scopeAnnotation, Annotation annotation) {
+    this.key = key;
+    this.scopeAnnotation = scopeAnnotation;
+    this.instance = instance;
+    this.dependencies = dependencies;
+    this.method = method;
+    this.parameterProviders = parameterProviders;
+    this.exposed = method.isAnnotationPresent(Exposed.class);
+    this.annotation = annotation;
+  }
+
+  @Override
+  public Key<T> getKey() {
+    return key;
+  }
+
+  @Override
+  public Method getMethod() {
+    return method;
+  }
+
+  // exposed for GIN
+  public Object getInstance() {
+    return instance;
+  }
+  
+  @Override
+  public Object getEnclosingInstance() {
+    return instance;
+  }
+  
+  @Override
+  public Annotation getAnnotation() {
+    return annotation;
+  }
+
+  public void configure(Binder binder) {
+    binder = binder.withSource(method);
+
+    if (scopeAnnotation != null) {
+      binder.bind(key).toProvider(this).in(scopeAnnotation);
+    } else {
+      binder.bind(key).toProvider(this);
+    }
+
+    if (exposed) {
+      // the cast is safe 'cause the only binder we have implements PrivateBinder. If there's a
+      // misplaced @Exposed, calling this will add an error to the binder's error queue
+      ((PrivateBinder) binder).expose(key);
+    }
+  }
+
+  @Override
+  public T get() {
+    Object[] parameters = new Object[parameterProviders.size()];
+    for (int i = 0; i < parameters.length; i++) {
+      parameters[i] = parameterProviders.get(i).get();
+    }
+
+    try {
+      @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" })
+      T result = (T) doProvision(parameters);
+      return result;
+    } catch (IllegalAccessException e) {
+      throw new AssertionError(e);
+    } catch (InvocationTargetException e) {
+      throw Exceptions.rethrowCause(e);
+    }
+  }
+
+  /** Extension point for our subclasses to implement the provisioning strategy. */
+  abstract Object doProvision(Object[] parameters)
+      throws IllegalAccessException, InvocationTargetException;
+
+  @Override
+  public Set<Dependency<?>> getDependencies() {
+    return dependencies;
+  }
+  
+  @Override
+  @SuppressWarnings("unchecked")
+  public <B, V> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor,
+      ProviderInstanceBinding<? extends B> binding) {
+    if (visitor instanceof ProvidesMethodTargetVisitor) {
+      return ((ProvidesMethodTargetVisitor<T, V>)visitor).visit(this);
+    }
+    return visitor.visit(binding);
+  }
+
+  @Override public String toString() {
+    String annotationString = annotation.toString();
+    // Show @Provides w/o the com.google.inject prefix.
+    if (annotation.annotationType() == Provides.class) {
+      annotationString = "@Provides";
+    } else if (annotationString.endsWith("()")) {
+      // Remove the common "()" suffix if there are no values.
+      annotationString = annotationString.substring(0, annotationString.length() - 2);
+    }
+    return annotationString + " " + StackTraceElements.forMember(method);
+  }
+  
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ProviderMethod) {
+      ProviderMethod<?> o = (ProviderMethod<?>) obj;
+      return method.equals(o.method)
+         && instance.equals(o.instance)
+         && annotation.equals(o.annotation);
+    } else {
+      return false;
+    }
+  }
+  
+  @Override
+  public int hashCode() {
+    // Avoid calling hashCode on 'instance', which is a user-object
+    // that might not be expecting it.
+    // (We need to call equals, so we do.  But we can avoid hashCode.)
+    return Objects.hashCode(method, annotation);
+  }
+
+  /*if[AOP]*/
+  /**
+   * A {@link ProviderMethod} implementation that uses {@link net.sf.cglib.reflect.FastClass#invoke}
+   * to invoke the provider method.
+   */
+  private static final class FastClassProviderMethod<T> extends ProviderMethod<T> {
+    final net.sf.cglib.reflect.FastClass fastClass;
+    final int methodIndex;
+
+    FastClassProviderMethod(Key<T> key,
+        Method method,
+        Object instance,
+        ImmutableSet<Dependency<?>> dependencies,
+        List<Provider<?>> parameterProviders,
+        Class<? extends Annotation> scopeAnnotation,
+        Annotation annotation) {
+      super(key,
+          method,
+          instance,
+          dependencies,
+          parameterProviders,
+          scopeAnnotation,
+          annotation);
+      // We need to generate a FastClass for the method's class, not the object's class.
+      this.fastClass =
+          BytecodeGen.newFastClass(method.getDeclaringClass(), Visibility.forMember(method));
+      // Use the Signature overload of getIndex because it properly uses return types to identify
+      // particular methods.  This is normally irrelevant, except in the case of covariant overrides
+      // which java implements with a compiler generated bridge method to implement the override.
+      this.methodIndex = fastClass.getIndex(
+          new net.sf.cglib.core.Signature(
+              method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
+      Preconditions.checkArgument(this.methodIndex >= 0, 
+          "Could not find method %s in fast class for class %s", 
+          method, 
+          method.getDeclaringClass());
+    }
+
+    @Override public Object doProvision(Object[] parameters)
+        throws IllegalAccessException, InvocationTargetException {
+      return fastClass.invoke(methodIndex, instance, parameters);
+    }
+  }
+  /*end[AOP]*/
+
+  /**
+   * A {@link ProviderMethod} implementation that invokes the method using normal java reflection. 
+   */
+  private static final class ReflectionProviderMethod<T> extends ProviderMethod<T> {
+    ReflectionProviderMethod(Key<T> key,
+        Method method,
+        Object instance,
+        ImmutableSet<Dependency<?>> dependencies,
+        List<Provider<?>> parameterProviders,
+        Class<? extends Annotation> scopeAnnotation,
+        Annotation annotation) {
+      super(key,
+          method,
+          instance,
+          dependencies,
+          parameterProviders,
+          scopeAnnotation,
+          annotation);
+    }
+
+    @Override Object doProvision(Object[] parameters) throws IllegalAccessException,
+        InvocationTargetException {
+      return method.invoke(instance, parameters);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProviderMethodsModule.java b/core/src/com/google/inject/internal/ProviderMethodsModule.java
new file mode 100644
index 0000000..7682dab
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProviderMethodsModule.java
@@ -0,0 +1,293 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.ModuleAnnotatedMethodScanner;
+import com.google.inject.util.Modules;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Creates bindings to methods annotated with {@literal @}{@link Provides}. Use the scope and
+ * binding annotations on the provider method to configure the binding.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public final class ProviderMethodsModule implements Module {
+
+  private static ModuleAnnotatedMethodScanner PROVIDES_BUILDER =
+      new ModuleAnnotatedMethodScanner() {
+        @Override
+        public <T> Key<T> prepareMethod(
+            Binder binder, Annotation annotation, Key<T> key, InjectionPoint injectionPoint) {
+          return key;
+        }
+
+        @Override
+        public Set<? extends Class<? extends Annotation>> annotationClasses() {
+          return ImmutableSet.of(Provides.class);
+        }
+      };
+
+  private final Object delegate;
+  private final TypeLiteral<?> typeLiteral;
+  private final boolean skipFastClassGeneration;
+  private final ModuleAnnotatedMethodScanner scanner;
+
+  private ProviderMethodsModule(Object delegate, boolean skipFastClassGeneration,
+      ModuleAnnotatedMethodScanner scanner) {
+    this.delegate = checkNotNull(delegate, "delegate");
+    this.typeLiteral = TypeLiteral.get(this.delegate.getClass());
+    this.skipFastClassGeneration = skipFastClassGeneration;
+    this.scanner = scanner;
+  }
+
+  /**
+   * Returns a module which creates bindings for provider methods from the given module.
+   */
+  public static Module forModule(Module module) {
+    return forObject(module, false, PROVIDES_BUILDER);
+  }
+
+  /**
+   * Returns a module which creates bindings methods in the module that match the scanner.
+   */
+  public static Module forModule(Object module, ModuleAnnotatedMethodScanner scanner) {
+    return forObject(module, false, scanner);
+  }
+
+  /**
+   * Returns a module which creates bindings for provider methods from the given object.
+   * This is useful notably for <a href="http://code.google.com/p/google-gin/">GIN</a>
+   *
+   * <p>This will skip bytecode generation for provider methods, since it is assumed that callers
+   * are only interested in Module metadata.
+   */
+  public static Module forObject(Object object) {
+    return forObject(object, true, PROVIDES_BUILDER);
+  }
+
+  private static Module forObject(Object object, boolean skipFastClassGeneration,
+      ModuleAnnotatedMethodScanner scanner) {
+    // avoid infinite recursion, since installing a module always installs itself
+    if (object instanceof ProviderMethodsModule) {
+      return Modules.EMPTY_MODULE;
+    }
+
+    return new ProviderMethodsModule(object, skipFastClassGeneration, scanner);
+  }
+
+  public Object getDelegateModule() {
+    return delegate;
+  }
+
+  @Override
+  public synchronized void configure(Binder binder) {
+    for (ProviderMethod<?> providerMethod : getProviderMethods(binder)) {
+      providerMethod.configure(binder);
+    }
+  }
+
+  public List<ProviderMethod<?>> getProviderMethods(Binder binder) {
+    List<ProviderMethod<?>> result = Lists.newArrayList();
+    Multimap<Signature, Method> methodsBySignature = HashMultimap.create();
+    for (Class<?> c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) {
+      for (Method method : c.getDeclaredMethods()) {
+        // private/static methods cannot override or be overridden by other methods, so there is no
+        // point in indexing them.
+        // Skip synthetic methods and bridge methods since java will automatically generate
+        // synthetic overrides in some cases where we don't want to generate an error (e.g.
+        // increasing visibility of a subclass).
+        if (((method.getModifiers() & (Modifier.PRIVATE | Modifier.STATIC)) == 0)
+            && !method.isBridge() && !method.isSynthetic()) {
+          methodsBySignature.put(new Signature(method), method);
+        }
+        Optional<Annotation> annotation = isProvider(binder, method);
+        if (annotation.isPresent()) {
+          result.add(createProviderMethod(binder, method, annotation.get()));
+        }
+      }
+    }
+    // we have found all the providers and now need to identify if any were overridden
+    // In the worst case this will have O(n^2) in the number of @Provides methods, but that is only
+    // assuming that every method is an override, in general it should be very quick.
+    for (ProviderMethod<?> provider : result) {
+      Method method = provider.getMethod();
+      for (Method matchingSignature : methodsBySignature.get(new Signature(method))) {
+        // matching signature is in the same class or a super class, therefore method cannot be
+        // overridding it.
+        if (matchingSignature.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) {
+          continue;
+        }
+        // now we know matching signature is in a subtype of method.getDeclaringClass()
+        if (overrides(matchingSignature, method)) {
+          String annotationString = provider.getAnnotation().annotationType() == Provides.class
+              ? "@Provides" : "@" + provider.getAnnotation().annotationType().getCanonicalName();
+          binder.addError(
+              "Overriding " + annotationString + " methods is not allowed."
+                  + "\n\t" + annotationString + " method: %s\n\toverridden by: %s",
+              method,
+              matchingSignature);
+          break;
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns true if the method is a provider.
+   *
+   * Synthetic bridge methods are excluded. Starting with JDK 8, javac copies annotations onto
+   * bridge methods (which always have erased signatures).
+   */
+  private Optional<Annotation> isProvider(Binder binder, Method method) {
+    if (method.isBridge() || method.isSynthetic()) {
+      return Optional.absent();
+    }
+    Annotation annotation = null;
+    for (Class<? extends Annotation> annotationClass : scanner.annotationClasses()) {
+      Annotation foundAnnotation = method.getAnnotation(annotationClass);
+      if (foundAnnotation != null) {
+        if (annotation != null) {
+          binder.addError("More than one annotation claimed by %s on method %s."
+              + " Methods can only have one annotation claimed per scanner.",
+              scanner, method);
+          return Optional.absent();
+        }
+        annotation = foundAnnotation;
+      }
+    }
+    return Optional.fromNullable(annotation);
+  }
+
+  private final class Signature {
+    final Class<?>[] parameters;
+    final String name;
+    final int hashCode;
+
+    Signature(Method method) {
+      this.name = method.getName();
+      // We need to 'resolve' the parameters against the actual class type in case this method uses
+      // type parameters.  This is so we can detect overrides of generic superclass methods where
+      // the subclass specifies the type parameter.  javac implements these kinds of overrides via
+      // bridge methods, but we don't want to give errors on bridge methods (but rather the target
+      // of the bridge).
+      List<TypeLiteral<?>> resolvedParameterTypes = typeLiteral.getParameterTypes(method);
+      this.parameters = new Class<?>[resolvedParameterTypes.size()];
+      int i = 0;
+      for (TypeLiteral<?> type : resolvedParameterTypes) {
+        parameters[i] = type.getRawType();
+      }
+      this.hashCode = name.hashCode() + 31 * Arrays.hashCode(parameters);
+    }
+
+    @Override public boolean equals(Object obj) {
+      if (obj instanceof Signature) {
+        Signature other = (Signature) obj;
+        return other.name.equals(name) && Arrays.equals(parameters, other.parameters);
+      }
+      return false;
+    }
+
+    @Override public int hashCode() {
+      return hashCode;
+    }
+  }
+
+  /** Returns true if a overrides b, assumes that the signatures match */
+  private static boolean overrides(Method a, Method b) {
+    // See JLS section 8.4.8.1
+    int modifiers = b.getModifiers();
+    if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
+      return true;
+    }
+    if (Modifier.isPrivate(modifiers)) {
+      return false;
+    }
+    // b must be package-private
+    return a.getDeclaringClass().getPackage().equals(b.getDeclaringClass().getPackage());
+  }
+
+  private <T> ProviderMethod<T> createProviderMethod(Binder binder, Method method,
+      Annotation annotation) {
+    binder = binder.withSource(method);
+    Errors errors = new Errors(method);
+
+    // prepare the parameter providers
+    InjectionPoint point = InjectionPoint.forMethod(method, typeLiteral);
+    List<Dependency<?>> dependencies = point.getDependencies();
+    List<Provider<?>> parameterProviders = Lists.newArrayList();
+    for (Dependency<?> dependency : point.getDependencies()) {
+      parameterProviders.add(binder.getProvider(dependency));
+    }
+
+    @SuppressWarnings("unchecked") // Define T as the method's return type.
+    TypeLiteral<T> returnType = (TypeLiteral<T>) typeLiteral.getReturnType(method);
+    Key<T> key = getKey(errors, returnType, method, method.getAnnotations());
+    try {
+      key = scanner.prepareMethod(binder, annotation, key, point);
+    } catch(Throwable t) {
+      binder.addError(t);
+    }
+    Class<? extends Annotation> scopeAnnotation
+        = Annotations.findScopeAnnotation(errors, method.getAnnotations());
+    for (Message message : errors.getMessages()) {
+      binder.addError(message);
+    }
+    return ProviderMethod.create(key, method, delegate, ImmutableSet.copyOf(dependencies),
+        parameterProviders, scopeAnnotation, skipFastClassGeneration, annotation);
+  }
+
+  <T> Key<T> getKey(Errors errors, TypeLiteral<T> type, Member member, Annotation[] annotations) {
+    Annotation bindingAnnotation = Annotations.findBindingAnnotation(errors, member, annotations);
+    return bindingAnnotation == null ? Key.get(type) : Key.get(type, bindingAnnotation);
+  }
+
+  @Override public boolean equals(Object o) {
+    return o instanceof ProviderMethodsModule
+        && ((ProviderMethodsModule) o).delegate == delegate
+        && ((ProviderMethodsModule) o).scanner == scanner;
+  }
+
+  @Override public int hashCode() {
+    return delegate.hashCode();
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java b/core/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java
new file mode 100644
index 0000000..672cf25
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java
@@ -0,0 +1,59 @@
+/**
+ * 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 com.google.inject.internal;
+
+import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.spi.Dependency;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+final class ProviderToInternalFactoryAdapter<T> implements Provider<T> {
+
+  private final InjectorImpl injector;
+  private final InternalFactory<? extends T> internalFactory;
+
+  public ProviderToInternalFactoryAdapter(InjectorImpl injector,
+      InternalFactory<? extends T> internalFactory) {
+    this.injector = injector;
+    this.internalFactory = internalFactory;
+  }
+
+  public T get() {
+    final Errors errors = new Errors();
+    try {
+      T t = injector.callInContext(new ContextualCallable<T>() {
+        public T call(InternalContext context) throws ErrorsException {
+          Dependency dependency = context.getDependency();
+          // Always pretend that we are a linked binding, to support
+          // scoping implicit bindings.  If we are not actually a linked
+          // binding, we'll fail properly elsewhere in the chain.
+          return internalFactory.get(errors, context, dependency, true);
+        }
+      });
+      errors.throwIfNewErrors(0);
+      return t;
+    } catch (ErrorsException e) {
+      throw new ProvisionException(errors.merge(e.getErrors()).getMessages());
+    }
+  }
+
+  @Override public String toString() {
+    return internalFactory.toString();
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java b/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java
new file mode 100644
index 0000000..1074628
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java
@@ -0,0 +1,128 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.internal;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Stage;
+import com.google.inject.spi.ProvisionListener;
+import com.google.inject.spi.ProvisionListenerBinding;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * {@link ProvisionListenerStackCallback} for each key.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+final class ProvisionListenerCallbackStore {
+
+  // TODO(sameb): Consider exposing this in the API somehow?  Maybe?
+  // Lots of code often want to skip over the internal stuffs.
+  private static final Set<Key<?>> INTERNAL_BINDINGS =
+      ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class));
+  
+  private final ImmutableList<ProvisionListenerBinding> listenerBindings;
+
+  private final LoadingCache<KeyBinding, ProvisionListenerStackCallback<?>> cache
+      = CacheBuilder.newBuilder().build(
+          new CacheLoader<KeyBinding, ProvisionListenerStackCallback<?>>() {
+            public ProvisionListenerStackCallback<?> load(KeyBinding key) {
+              return create(key.binding);
+            }
+          });
+
+  ProvisionListenerCallbackStore(List<ProvisionListenerBinding> listenerBindings) {
+    this.listenerBindings = ImmutableList.copyOf(listenerBindings);
+  }
+
+  /** Returns a new {@link ProvisionListenerStackCallback} for the key.
+   */
+  @SuppressWarnings("unchecked") // the ProvisionListenerStackCallback type always agrees with the passed type
+  public <T> ProvisionListenerStackCallback<T> get(Binding<T> binding) {
+    // Never notify any listeners for internal bindings.
+    if (!INTERNAL_BINDINGS.contains(binding.getKey())) {
+      return (ProvisionListenerStackCallback<T>) cache.getUnchecked(
+          new KeyBinding(binding.getKey(), binding));
+    }
+    return ProvisionListenerStackCallback.emptyListener();
+  }
+
+  /**
+   * Purges a key from the cache. Use this only if the type is not actually valid for
+   * binding and needs to be purged. (See issue 319 and
+   * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and
+   * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is
+   * necessary.)
+   * 
+   * Returns true if the type was stored in the cache, false otherwise.
+   */
+  boolean remove(Binding<?> type) {
+    return cache.asMap().remove(type) != null;
+  }
+
+  /**
+   * Creates a new {@link ProvisionListenerStackCallback} with the correct listeners
+   * for the key.
+   */
+  private <T> ProvisionListenerStackCallback<T> create(Binding<T> binding) {
+    List<ProvisionListener> listeners = null;
+    for (ProvisionListenerBinding provisionBinding : listenerBindings) {
+      if (provisionBinding.getBindingMatcher().matches(binding)) {
+        if (listeners == null) {
+          listeners = Lists.newArrayList();
+        }
+        listeners.addAll(provisionBinding.getListeners());
+      }
+    }
+    if (listeners == null || listeners.isEmpty()) {
+      // Optimization: don't bother constructing the callback if there are
+      // no listeners.
+      return ProvisionListenerStackCallback.emptyListener();
+    }
+    return new ProvisionListenerStackCallback<T>(binding, listeners);
+  }
+  
+  /** A struct that holds key & binding but uses just key for equality/hashcode. */
+  private static class KeyBinding {
+    final Key<?> key;
+    final Binding<?> binding;
+    
+    KeyBinding(Key<?> key, Binding<?> binding) {
+      this.key = key;
+      this.binding = binding;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+      return obj instanceof KeyBinding && key.equals(((KeyBinding)obj).key);
+    }
+    @Override
+    public int hashCode() {
+      return key.hashCode();
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java b/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java
new file mode 100644
index 0000000..f72da25
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.ProvisionException;
+import com.google.inject.spi.DependencyAndSource;
+import com.google.inject.spi.ProvisionListener;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Intercepts provisions with a stack of listeners.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+final class ProvisionListenerStackCallback<T> {
+  
+  private static final ProvisionListener EMPTY_LISTENER[] = new ProvisionListener[0];
+  @SuppressWarnings("rawtypes")
+  private static final ProvisionListenerStackCallback<?> EMPTY_CALLBACK =
+      new ProvisionListenerStackCallback(null /* unused, so ok */, ImmutableList.of());
+
+  private final ProvisionListener[] listeners;
+  private final Binding<T> binding;
+  
+  @SuppressWarnings("unchecked")
+  public static <T> ProvisionListenerStackCallback<T> emptyListener() {
+    return (ProvisionListenerStackCallback<T>) EMPTY_CALLBACK;
+  }
+
+  public ProvisionListenerStackCallback(Binding<T> binding, List<ProvisionListener> listeners) {
+    this.binding = binding;
+    if (listeners.isEmpty()) {
+      this.listeners = EMPTY_LISTENER;
+    } else {
+      Set<ProvisionListener> deDuplicated = Sets.newLinkedHashSet(listeners);
+      this.listeners = deDuplicated.toArray(new ProvisionListener[deDuplicated.size()]);
+    }
+  }
+  
+  public boolean hasListeners() {
+    return listeners.length > 0;
+  }
+
+  public T provision(Errors errors, InternalContext context, ProvisionCallback<T> callable)
+      throws ErrorsException {
+    Provision provision = new Provision(errors, context, callable);
+    RuntimeException caught = null;
+    try {
+      provision.provision();
+    } catch(RuntimeException t) {
+      caught = t;
+    }
+    
+    if (provision.exceptionDuringProvision != null) {
+      throw provision.exceptionDuringProvision;
+    } else if (caught != null) {
+      Object listener = provision.erredListener != null ?
+          provision.erredListener.getClass() : "(unknown)";
+      throw errors
+          .errorInUserCode(caught, "Error notifying ProvisionListener %s of %s.%n"
+              + " Reason: %s", listener, binding.getKey(), caught)
+          .toException();
+    } else {
+      return provision.result;
+    }
+  }
+
+  // TODO(sameb): Can this be more InternalFactory-like?
+  public interface ProvisionCallback<T> {
+    public T call() throws ErrorsException;
+  }
+
+  private class Provision extends ProvisionListener.ProvisionInvocation<T> {
+
+    final Errors errors;
+    final int numErrorsBefore;
+    final InternalContext context;
+    final ProvisionCallback<T> callable;
+    int index = -1;
+    T result;
+    ErrorsException exceptionDuringProvision;
+    ProvisionListener erredListener;
+
+    public Provision(Errors errors, InternalContext context, ProvisionCallback<T> callable) {
+      this.callable = callable;
+      this.context = context;
+      this.errors = errors;
+      this.numErrorsBefore = errors.size();
+    }
+
+    @Override
+    public T provision() {
+      index++;
+      if (index == listeners.length) {
+        try {
+          result = callable.call();
+          // Make sure we don't return the provisioned object if there were any errors
+          // injecting its field/method dependencies.
+          errors.throwIfNewErrors(numErrorsBefore);
+        } catch(ErrorsException ee) {
+          exceptionDuringProvision = ee;
+          throw new ProvisionException(errors.merge(ee.getErrors()).getMessages());
+        }
+      } else if (index < listeners.length) {
+        int currentIdx = index;
+        try {
+          listeners[index].onProvision(this);
+        } catch(RuntimeException re) {
+          erredListener = listeners[currentIdx];
+          throw re;
+        }
+        if (currentIdx == index) {
+          // Our listener didn't provision -- do it for them.
+          provision();
+        }
+      } else {
+        throw new IllegalStateException("Already provisioned in this listener.");
+      }
+      return result;
+    }
+    
+    @Override
+    public Binding<T> getBinding() {
+      // TODO(sameb): Because so many places cast directly to BindingImpl & subclasses,
+      // we can't decorate this to prevent calling getProvider().get(), which means
+      // if someone calls that they'll get strange errors.
+      return binding;
+    }
+    
+    @Override
+    public List<DependencyAndSource> getDependencyChain() {
+      return context.getDependencyChain();
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ProxyFactory.java b/core/src/com/google/inject/internal/ProxyFactory.java
new file mode 100644
index 0000000..13aff81
--- /dev/null
+++ b/core/src/com/google/inject/internal/ProxyFactory.java
@@ -0,0 +1,284 @@
+/**
+ * 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 com.google.inject.internal;
+
+import static com.google.inject.internal.BytecodeGen.newFastClass;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.spi.InjectionPoint;
+
+import net.sf.cglib.core.MethodWrapper;
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.CallbackFilter;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.reflect.FastClass;
+import net.sf.cglib.reflect.FastConstructor;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Builds a construction proxy that can participate in AOP. This class manages applying type and
+ * method matchers to come up with the set of intercepted methods.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class ProxyFactory<T> implements ConstructionProxyFactory<T> {
+  
+  private static final Logger logger = Logger.getLogger(ProxyFactory.class.getName());
+
+  private final InjectionPoint injectionPoint;
+  private final ImmutableMap<Method, List<MethodInterceptor>> interceptors;
+  private final Class<T> declaringClass;
+  private final List<Method> methods;
+  private final Callback[] callbacks;
+
+  /**
+   * PUBLIC is default; it's used if all the methods we're intercepting are public. This impacts
+   * which classloader we should use for loading the enhanced class
+   */
+  private BytecodeGen.Visibility visibility = BytecodeGen.Visibility.PUBLIC;
+
+  ProxyFactory(InjectionPoint injectionPoint, Iterable<MethodAspect> methodAspects) {
+    this.injectionPoint = injectionPoint;
+
+    @SuppressWarnings("unchecked") // the member of injectionPoint is always a Constructor<T>
+        Constructor<T> constructor = (Constructor<T>) injectionPoint.getMember();
+    declaringClass = constructor.getDeclaringClass();
+
+    // Find applicable aspects. Bow out if none are applicable to this class.
+    List<MethodAspect> applicableAspects = Lists.newArrayList();
+    for (MethodAspect methodAspect : methodAspects) {
+      if (methodAspect.matches(declaringClass)) {
+        applicableAspects.add(methodAspect);
+      }
+    }
+
+    if (applicableAspects.isEmpty()) {
+      interceptors = ImmutableMap.of();
+      methods = ImmutableList.of();
+      callbacks = null;
+      return;
+    }
+
+    // Get list of methods from cglib.
+    methods = Lists.newArrayList();
+    Enhancer.getMethods(declaringClass, null, methods);
+
+    // Create method/interceptor holders and record indices.
+    List<MethodInterceptorsPair> methodInterceptorsPairs = Lists.newArrayList();
+    for (Method method : methods) {
+      methodInterceptorsPairs.add(new MethodInterceptorsPair(method));
+    }
+
+    // Iterate over aspects and add interceptors for the methods they apply to
+    boolean anyMatched = false;
+    for (MethodAspect methodAspect : applicableAspects) {
+      for (MethodInterceptorsPair pair : methodInterceptorsPairs) {
+        if (methodAspect.matches(pair.method)) {
+          if(pair.method.isSynthetic()) {
+            logger.log(Level.WARNING,
+                "Method [{0}] is synthetic and is being intercepted by {1}."
+              + " This could indicate a bug.  The method may be intercepted twice,"
+              + " or may not be intercepted at all.",
+                new Object[] { pair.method, methodAspect.interceptors() });
+          }
+          visibility = visibility.and(BytecodeGen.Visibility.forMember(pair.method));
+          pair.addAll(methodAspect.interceptors());
+          anyMatched = true;
+        }
+      }
+    }
+
+    if (!anyMatched) {
+      interceptors = ImmutableMap.of();
+      callbacks = null;
+      return;
+    }
+
+    ImmutableMap.Builder<Method, List<MethodInterceptor>> interceptorsMapBuilder = null; // lazy
+
+    callbacks = new Callback[methods.size()];
+    for (int i = 0; i < methods.size(); i++) {
+      MethodInterceptorsPair pair = methodInterceptorsPairs.get(i);
+
+      if (!pair.hasInterceptors()) {
+        callbacks[i] = net.sf.cglib.proxy.NoOp.INSTANCE;
+        continue;
+      }
+
+      if (interceptorsMapBuilder == null) {
+        interceptorsMapBuilder = ImmutableMap.builder();
+      }
+
+      ImmutableList<MethodInterceptor> deDuplicated =
+          ImmutableSet.copyOf(pair.interceptors).asList();
+      interceptorsMapBuilder.put(pair.method, deDuplicated);
+      callbacks[i] = new InterceptorStackCallback(pair.method, deDuplicated);
+    }
+
+    interceptors = interceptorsMapBuilder != null
+        ? interceptorsMapBuilder.build()
+        : ImmutableMap.<Method, List<MethodInterceptor>>of();
+  }
+
+  /**
+   * Returns the interceptors that apply to the constructed type.
+   */
+  public ImmutableMap<Method, List<MethodInterceptor>> getInterceptors() {
+    return interceptors;
+  }
+
+  public ConstructionProxy<T> create() throws ErrorsException {
+    if (interceptors.isEmpty()) {
+      return new DefaultConstructionProxyFactory<T>(injectionPoint).create();
+    }
+
+    @SuppressWarnings("unchecked")
+    Class<? extends Callback>[] callbackTypes = new Class[callbacks.length];
+    for (int i = 0; i < callbacks.length; i++) {
+      if (callbacks[i] == net.sf.cglib.proxy.NoOp.INSTANCE) {
+        callbackTypes[i] = net.sf.cglib.proxy.NoOp.class;
+      } else {
+        callbackTypes[i] = net.sf.cglib.proxy.MethodInterceptor.class;
+      }
+    }
+
+    // Create the proxied class. We're careful to ensure that all enhancer state is not-specific
+    // to this injector. Otherwise, the proxies for each injector will waste PermGen memory
+    try {
+    Enhancer enhancer = BytecodeGen.newEnhancer(declaringClass, visibility);
+    enhancer.setCallbackFilter(new IndicesCallbackFilter(methods));
+    enhancer.setCallbackTypes(callbackTypes);
+    return new ProxyConstructor<T>(enhancer, injectionPoint, callbacks, interceptors);
+    } catch (Throwable e) {
+      throw new Errors().errorEnhancingClass(declaringClass, e).toException();
+    }
+  }
+
+  private static class MethodInterceptorsPair {
+    final Method method;
+    List<MethodInterceptor> interceptors; // lazy
+
+    MethodInterceptorsPair(Method method) {
+      this.method = method;
+    }
+
+    void addAll(List<MethodInterceptor> interceptors) {
+      if (this.interceptors == null) {
+        this.interceptors = Lists.newArrayList();
+      }
+      this.interceptors.addAll(interceptors);
+    }
+
+    boolean hasInterceptors() {
+      return interceptors != null;
+    }
+  }
+
+  /**
+   * A callback filter that maps methods to unique IDs. We define equals and
+   * hashCode without using any state related to the injector so that enhanced
+   * classes intercepting the same methods can be shared between injectors (and
+   * child injectors, etc).
+   */
+  private static class IndicesCallbackFilter implements CallbackFilter {
+    final Map<Object, Integer> indices;
+    final int hashCode;
+
+    IndicesCallbackFilter(List<Method> methods) {
+      final Map<Object, Integer> indices = Maps.newHashMap();
+      for (int i = 0; i < methods.size(); i++) {
+        indices.put(MethodWrapper.create(methods.get(i)), i);
+      }
+      this.indices = indices;
+      this.hashCode = indices.hashCode();
+    }
+
+    public int accept(Method method) {
+      return indices.get(MethodWrapper.create(method));
+    }
+
+    @Override public boolean equals(Object o) {
+      return o instanceof IndicesCallbackFilter &&
+          ((IndicesCallbackFilter) o).indices.equals(indices);
+    }
+
+    @Override public int hashCode() {
+      return hashCode;
+    }
+  }
+
+  /**
+   * Constructs instances that participate in AOP.
+   */
+  private static class ProxyConstructor<T> implements ConstructionProxy<T> {
+    final Class<?> enhanced;
+    final InjectionPoint injectionPoint;
+    final Constructor<T> constructor;
+    final Callback[] callbacks;
+
+    final FastConstructor fastConstructor;
+    final ImmutableMap<Method, List<MethodInterceptor>> methodInterceptors;
+
+    @SuppressWarnings("unchecked") // the constructor promises to construct 'T's
+    ProxyConstructor(Enhancer enhancer, InjectionPoint injectionPoint, Callback[] callbacks,
+        ImmutableMap<Method, List<MethodInterceptor>> methodInterceptors) {
+      this.enhanced = enhancer.createClass(); // this returns a cached class if possible
+      this.injectionPoint = injectionPoint;
+      this.constructor = (Constructor<T>) injectionPoint.getMember();
+      this.callbacks = callbacks;
+      this.methodInterceptors = methodInterceptors;
+
+      FastClass fastClass = newFastClass(enhanced, BytecodeGen.Visibility.forMember(constructor));
+      this.fastConstructor = fastClass.getConstructor(constructor.getParameterTypes());
+    }
+
+    @SuppressWarnings("unchecked") // the constructor promises to produce 'T's
+    public T newInstance(Object... arguments) throws InvocationTargetException {
+      Enhancer.registerCallbacks(enhanced, callbacks);
+      try {
+        return (T) fastConstructor.newInstance(arguments);
+      } finally {
+        Enhancer.registerCallbacks(enhanced, null);
+      }
+    }
+
+    public InjectionPoint getInjectionPoint() {
+      return injectionPoint;
+    }
+
+    public Constructor<T> getConstructor() {
+      return constructor;
+    }
+
+    public ImmutableMap<Method, List<MethodInterceptor>> getMethodInterceptors() {
+      return methodInterceptors;
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/ScopeBindingProcessor.java b/core/src/com/google/inject/internal/ScopeBindingProcessor.java
new file mode 100644
index 0000000..3e68b30
--- /dev/null
+++ b/core/src/com/google/inject/internal/ScopeBindingProcessor.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Scope;
+import com.google.inject.spi.ScopeBinding;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Handles {@code Binder.bindScope} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class ScopeBindingProcessor extends AbstractProcessor {
+
+  ScopeBindingProcessor(Errors errors) {
+    super(errors);
+  }
+
+  @Override public Boolean visit(ScopeBinding command) {
+    Scope scope = checkNotNull(command.getScope(), "scope");
+    Class<? extends Annotation> annotationType = checkNotNull(command.getAnnotationType(), "annotation type");
+
+    if (!Annotations.isScopeAnnotation(annotationType)) {
+      errors.missingScopeAnnotation(annotationType);
+      // Go ahead and bind anyway so we don't get collateral errors.
+    }
+
+    if (!Annotations.isRetainedAtRuntime(annotationType)) {
+      errors.missingRuntimeRetention(annotationType);
+      // Go ahead and bind anyway so we don't get collateral errors.
+    }
+
+    ScopeBinding existing = injector.state.getScopeBinding(annotationType);
+    if (existing != null) {
+      if (!scope.equals(existing.getScope())) {
+        errors.duplicateScopes(existing, annotationType, scope);
+      }
+    } else {
+      injector.state.putScopeBinding(annotationType, command);
+    }
+
+    return true;
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/Scoping.java b/core/src/com/google/inject/internal/Scoping.java
new file mode 100644
index 0000000..334aaef
--- /dev/null
+++ b/core/src/com/google/inject/internal/Scoping.java
@@ -0,0 +1,266 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.Scopes;
+import com.google.inject.Singleton;
+import com.google.inject.Stage;
+import com.google.inject.binder.ScopedBindingBuilder;
+import com.google.inject.spi.BindingScopingVisitor;
+import com.google.inject.spi.ScopeBinding;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * References a scope, either directly (as a scope instance), or indirectly (as a scope annotation).
+ * The scope's eager or laziness is also exposed.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public abstract class Scoping {
+
+  /**
+   * No scoping annotation has been applied. Note that this is different from {@code
+   * in(Scopes.NO_SCOPE)}, where the 'NO_SCOPE' has been explicitly applied.
+   */
+  public static final Scoping UNSCOPED = new Scoping() {
+    @Override public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
+      return visitor.visitNoScoping();
+    }
+
+    @Override public Scope getScopeInstance() {
+      return Scopes.NO_SCOPE;
+    }
+
+    @Override public String toString() {
+      return Scopes.NO_SCOPE.toString();
+    }
+
+    @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) {
+      // do nothing
+    }
+  };
+
+  public static final Scoping SINGLETON_ANNOTATION = new Scoping() {
+    @Override public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
+      return visitor.visitScopeAnnotation(Singleton.class);
+    }
+
+    @Override public Class<? extends Annotation> getScopeAnnotation() {
+      return Singleton.class;
+    }
+
+    @Override public String toString() {
+      return Singleton.class.getName();
+    }
+
+    @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) {
+      scopedBindingBuilder.in(Singleton.class);
+    }
+  };
+
+  public static final Scoping SINGLETON_INSTANCE = new Scoping() {
+    @Override public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
+      return visitor.visitScope(Scopes.SINGLETON);
+    }
+
+    @Override public Scope getScopeInstance() {
+      return Scopes.SINGLETON;
+    }
+
+    @Override public String toString() {
+      return Scopes.SINGLETON.toString();
+    }
+
+    @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) {
+      scopedBindingBuilder.in(Scopes.SINGLETON);
+    }
+  };
+
+  public static final Scoping EAGER_SINGLETON = new Scoping() {
+    @Override public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
+      return visitor.visitEagerSingleton();
+    }
+
+    @Override public Scope getScopeInstance() {
+      return Scopes.SINGLETON;
+    }
+
+    @Override public String toString() {
+      return "eager singleton";
+    }
+
+    @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) {
+      scopedBindingBuilder.asEagerSingleton();
+    }
+  };
+
+  public static Scoping forAnnotation(final Class<? extends Annotation> scopingAnnotation) {
+    if (scopingAnnotation == Singleton.class
+        || scopingAnnotation == javax.inject.Singleton.class) {
+      return SINGLETON_ANNOTATION;
+    }
+
+    return new Scoping() {
+      @Override public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
+        return visitor.visitScopeAnnotation(scopingAnnotation);
+      }
+
+      @Override public Class<? extends Annotation> getScopeAnnotation() {
+        return scopingAnnotation;
+      }
+
+      @Override public String toString() {
+        return scopingAnnotation.getName();
+      }
+
+      @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) {
+        scopedBindingBuilder.in(scopingAnnotation);
+      }
+    };
+  }
+
+  public static Scoping forInstance(final Scope scope) {
+    if (scope == Scopes.SINGLETON) {
+      return SINGLETON_INSTANCE;
+    }
+
+    return new Scoping() {
+      @Override public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
+        return visitor.visitScope(scope);
+      }
+
+      @Override public Scope getScopeInstance() {
+        return scope;
+      }
+
+      @Override public String toString() {
+        return scope.toString();
+      }
+
+      @Override public void applyTo(ScopedBindingBuilder scopedBindingBuilder) {
+        scopedBindingBuilder.in(scope);
+      }
+    };
+  }
+
+  /**
+   * Returns true if this scope was explicitly applied. If no scope was explicitly applied then the
+   * scoping annotation will be used.
+   */
+  public boolean isExplicitlyScoped() {
+    return this != UNSCOPED;
+  }
+
+  /**
+   * Returns true if this is the default scope. In this case a new instance will be provided for
+   * each injection.
+   */
+  public boolean isNoScope() {
+    return getScopeInstance() == Scopes.NO_SCOPE;
+  }
+
+  /**
+   * Returns true if this scope is a singleton that should be loaded eagerly in {@code stage}.
+   */
+  public boolean isEagerSingleton(Stage stage) {
+    if (this == EAGER_SINGLETON) {
+      return true;
+    }
+
+    if (stage == Stage.PRODUCTION) {
+      return this == SINGLETON_ANNOTATION || this == SINGLETON_INSTANCE;
+    }
+
+    return false;
+  }
+
+  /**
+   * Returns the scope instance, or {@code null} if that isn't known for this instance.
+   */
+  public Scope getScopeInstance() {
+    return null;
+  }
+
+  /**
+   * Returns the scope annotation, or {@code null} if that isn't known for this instance.
+   */
+  public Class<? extends Annotation> getScopeAnnotation() {
+    return null;
+  }
+  
+  @Override
+  public boolean equals(Object obj) {
+    if(obj instanceof Scoping) {
+      Scoping o = (Scoping)obj;
+      return Objects.equal(getScopeAnnotation(), o.getScopeAnnotation())
+        && Objects.equal(getScopeInstance(), o.getScopeInstance());
+    } else {
+      return false;
+    }
+  }
+  
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(getScopeAnnotation(), getScopeInstance());
+  }
+
+  public abstract <V> V acceptVisitor(BindingScopingVisitor<V> visitor);
+
+  public abstract void applyTo(ScopedBindingBuilder scopedBindingBuilder);
+
+  private Scoping() {}
+
+  /** Scopes an internal factory. */
+  static <T> InternalFactory<? extends T> scope(Key<T> key, InjectorImpl injector,
+      InternalFactory<? extends T> creator, Object source, Scoping scoping) {
+
+    if (scoping.isNoScope()) {
+      return creator;
+    }
+
+    Scope scope = scoping.getScopeInstance();
+
+    Provider<T> scoped
+        = scope.scope(key, new ProviderToInternalFactoryAdapter<T>(injector, creator));
+    return new InternalFactoryToProviderAdapter<T>(scoped, source);
+  }
+
+  /**
+   * Replaces annotation scopes with instance scopes using the Injector's annotation-to-instance
+   * map. If the scope annotation has no corresponding instance, an error will be added and unscoped
+   * will be retuned.
+   */
+  static Scoping makeInjectable(Scoping scoping, InjectorImpl injector, Errors errors) {
+    Class<? extends Annotation> scopeAnnotation = scoping.getScopeAnnotation();
+    if (scopeAnnotation == null) {
+      return scoping;
+    }
+
+    ScopeBinding scope = injector.state.getScopeBinding(scopeAnnotation);
+    if (scope != null) {
+      return forInstance(scope.getScope());
+    }
+
+    errors.scopeNotFound(scopeAnnotation);
+    return UNSCOPED;
+  }
+}
diff --git a/core/src/com/google/inject/internal/SingleFieldInjector.java b/core/src/com/google/inject/internal/SingleFieldInjector.java
new file mode 100644
index 0000000..52be1f4
--- /dev/null
+++ b/core/src/com/google/inject/internal/SingleFieldInjector.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.internal.InjectorImpl.JitLimitation;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.InjectionPoint;
+
+import java.lang.reflect.Field;
+
+/**
+ * Sets an injectable field.
+ */
+final class SingleFieldInjector implements SingleMemberInjector {
+  final Field field;
+  final InjectionPoint injectionPoint;
+  final Dependency<?> dependency;
+  final BindingImpl<?> binding;
+
+  public SingleFieldInjector(InjectorImpl injector, InjectionPoint injectionPoint, Errors errors)
+      throws ErrorsException {
+    this.injectionPoint = injectionPoint;
+    this.field = (Field) injectionPoint.getMember();
+    this.dependency = injectionPoint.getDependencies().get(0);
+
+    // Ewwwww...
+    field.setAccessible(true);
+    binding = injector.getBindingOrThrow(dependency.getKey(), errors, JitLimitation.NO_JIT);
+  }
+
+  public InjectionPoint getInjectionPoint() {
+    return injectionPoint;
+  }
+
+  public void inject(Errors errors, InternalContext context, Object o) {
+    errors = errors.withSource(dependency);
+
+    Dependency previous = context.pushDependency(dependency, binding.getSource());
+    try {
+      Object value = binding.getInternalFactory().get(errors, context, dependency, false);
+      field.set(o, value);
+    } catch (ErrorsException e) {
+      errors.withSource(injectionPoint).merge(e.getErrors());
+    } catch (IllegalAccessException e) {
+      throw new AssertionError(e); // a security manager is blocking us, we're hosed
+    } finally {
+      context.popStateAndSetDependency(previous);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/SingleMemberInjector.java b/core/src/com/google/inject/internal/SingleMemberInjector.java
new file mode 100644
index 0000000..fea5733
--- /dev/null
+++ b/core/src/com/google/inject/internal/SingleMemberInjector.java
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.spi.InjectionPoint;
+
+/**
+ * Injects a field or method of a given object.
+ */
+interface SingleMemberInjector {
+  void inject(Errors errors, InternalContext context, Object o);
+  InjectionPoint getInjectionPoint();
+}
diff --git a/core/src/com/google/inject/internal/SingleMethodInjector.java b/core/src/com/google/inject/internal/SingleMethodInjector.java
new file mode 100644
index 0000000..8bc8a34
--- /dev/null
+++ b/core/src/com/google/inject/internal/SingleMethodInjector.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.internal.BytecodeGen.Visibility;
+import com.google.inject.internal.InjectorImpl.MethodInvoker;
+import com.google.inject.spi.InjectionPoint;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Invokes an injectable method.
+ */
+final class SingleMethodInjector implements SingleMemberInjector {
+  private final MethodInvoker methodInvoker;
+  private final SingleParameterInjector<?>[] parameterInjectors;
+  private final InjectionPoint injectionPoint;
+
+  SingleMethodInjector(InjectorImpl injector, InjectionPoint injectionPoint, Errors errors)
+      throws ErrorsException {
+    this.injectionPoint = injectionPoint;
+    final Method method = (Method) injectionPoint.getMember();
+    methodInvoker = createMethodInvoker(method);
+    parameterInjectors = injector.getParametersInjectors(injectionPoint.getDependencies(), errors);
+  }
+
+  private MethodInvoker createMethodInvoker(final Method method) {
+
+    // We can't use FastMethod if the method is private.
+    int modifiers = method.getModifiers();
+    if (!Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers)) {
+      /*if[AOP]*/
+      try {
+      final net.sf.cglib.reflect.FastMethod fastMethod
+          = BytecodeGen.newFastClass(method.getDeclaringClass(), Visibility.forMember(method))
+              .getMethod(method);
+
+      return new MethodInvoker() {
+        public Object invoke(Object target, Object... parameters)
+            throws IllegalAccessException, InvocationTargetException {
+          return fastMethod.invoke(target, parameters);
+        }
+      };
+      } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */}
+      /*end[AOP]*/
+    }
+
+    if (!Modifier.isPublic(modifiers) ||
+        !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
+      method.setAccessible(true);
+    }
+
+    return new MethodInvoker() {
+      public Object invoke(Object target, Object... parameters)
+          throws IllegalAccessException, InvocationTargetException {
+        return method.invoke(target, parameters);
+      }
+    };
+  }
+
+  public InjectionPoint getInjectionPoint() {
+    return injectionPoint;
+  }
+
+  public void inject(Errors errors, InternalContext context, Object o) {
+    Object[] parameters;
+    try {
+      parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors);
+    } catch (ErrorsException e) {
+      errors.merge(e.getErrors());
+      return;
+    }
+
+    try {
+      methodInvoker.invoke(o, parameters);
+    } catch (IllegalAccessException e) {
+      throw new AssertionError(e); // a security manager is blocking us, we're hosed
+    } catch (InvocationTargetException userException) {
+      Throwable cause = userException.getCause() != null
+          ? userException.getCause()
+          : userException;
+      errors.withSource(injectionPoint).errorInjectingMethod(cause);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/SingleParameterInjector.java b/core/src/com/google/inject/internal/SingleParameterInjector.java
new file mode 100644
index 0000000..708b8b0
--- /dev/null
+++ b/core/src/com/google/inject/internal/SingleParameterInjector.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.spi.Dependency;
+
+/**
+ * Resolves a single parameter, to be used in a constructor or method invocation.
+ */
+final class SingleParameterInjector<T> {
+  private static final Object[] NO_ARGUMENTS = {}; 
+
+  private final Dependency<T> dependency;
+  private final BindingImpl<? extends T> binding;
+
+  SingleParameterInjector(Dependency<T> dependency, BindingImpl<? extends T> binding) {
+    this.dependency = dependency;
+    this.binding = binding;
+  }
+
+  private T inject(Errors errors, InternalContext context) throws ErrorsException {
+    Dependency previous = context.pushDependency(dependency, binding.getSource());
+    try {
+      return binding.getInternalFactory().get(errors.withSource(dependency), context, dependency, false);
+    } finally {
+      context.popStateAndSetDependency(previous);
+    }
+  }
+
+  /**
+   * Returns an array of parameter values.
+   */
+  static Object[] getAll(Errors errors, InternalContext context,
+      SingleParameterInjector<?>[] parameterInjectors) throws ErrorsException {
+    if (parameterInjectors == null) {
+      return NO_ARGUMENTS;
+    }
+
+    int numErrorsBefore = errors.size();
+
+    int size = parameterInjectors.length;
+    Object[] parameters = new Object[size];
+
+    // optimization: use manual for/each to save allocating an iterator here  
+    for (int i = 0; i < size; i++) {
+      SingleParameterInjector<?> parameterInjector = parameterInjectors[i];
+      try {
+        parameters[i] = parameterInjector.inject(errors, context);
+      } catch (ErrorsException e) {
+        errors.merge(e.getErrors());
+      }
+    }
+
+    errors.throwIfNewErrors(numErrorsBefore);
+    return parameters;
+  }
+}
diff --git a/core/src/com/google/inject/internal/SingletonScope.java b/core/src/com/google/inject/internal/SingletonScope.java
new file mode 100644
index 0000000..fe6287a
--- /dev/null
+++ b/core/src/com/google/inject/internal/SingletonScope.java
@@ -0,0 +1,343 @@
+package com.google.inject.internal;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.Scope;
+import com.google.inject.Scopes;
+import com.google.inject.Singleton;
+import com.google.inject.internal.CycleDetectingLock.CycleDetectingLockFactory;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.DependencyAndSource;
+import com.google.inject.spi.Message;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * One instance per {@link Injector}. Also see {@code @}{@link Singleton}.
+ *
+ * Introduction from the author:
+ * Implementation of this class seems unreasonably complicated at the first sight.
+ * I fully agree with you, that the beast below is very complex
+ * and it's hard to reason on how does it work or not.
+ * Still I want to assure you that hundreds(?) of hours were thrown
+ * into making this code simple, while still maintaining Singleton contract.
+ *
+ * Anyway, why is it so complex? Singleton scope does not seem to be that unique.
+ * 1) Guice has never truly expected to be used in multi threading environment
+ *    with many Injectors working alongside each other. There is almost no
+ *    code with Guice that propagates state between threads. And Singleton
+ *    scope is The exception.
+ * 2) Guice supports circular dependencies and thus manages proxy objects.
+ *    There is no interface that allows user defined Scopes to create proxies,
+ *    it is expected to be done by Guice. Singleton scope needs to be
+ *    able to detect circular dependencies spanning several threads,
+ *    therefore Singleton scope needs to be able to create these proxies.
+ * 3) To make things worse, Guice has a very tricky definition for a binding
+ *    resolution when Injectors are in in a parent/child relationship.
+ *    And Scope does not have access to this information by design,
+ *    the only real action that Scope can do is to call or not to call a creator.
+ * 4) There is no readily available code in Guice that can detect a potential
+ *    deadlock, and no code for handling dependency cycles spanning several threads.
+ *    This is significantly harder as all the dependencies in a thread at runtime
+ *    can be represented with a list, where in a multi threaded environment
+ *    we have more complex dependency trees.
+ * 5) Guice has a pretty strong contract regarding Garbage Collection,
+ *    which often prevents us from linking objects directly.
+ *    So simple domain specific code can not be written and intermediary
+ *    id objects need to be managed.
+ * 6) Guice is relatively fast and we should not make things worse.
+ *    We're trying our best to optimize synchronization for speed and memory.
+ *    Happy path should be almost as fast as in a single threaded solution
+ *    and should not take much more memory.
+ * 7) Error message generation in Guice was not meant to be used like this and to work around
+ *    its APIs we need a lot of code. Additional complexity comes from inherent data races
+ *    as message is only generated when failure occurs on proxy object generation.
+ * Things get ugly pretty fast.
+ *
+ * @see #scope(Key, Provider)
+ * @see CycleDetectingLock
+ *
+ * @author timofeyb (Timothy Basanov)
+ */
+public class SingletonScope implements Scope {
+
+  /** A sentinel value representing null. */
+  private static final Object NULL = new Object();
+
+  /**
+   * Allows us to detect when circular proxies are necessary. It's only used during singleton
+   * instance initialization, after initialization direct access through volatile field is used.
+   *
+   * NB: Factory uses {@link Key}s as a user locks ids, different injectors can
+   * share them. Cycles are detected properly as cycle detection does not rely on user locks ids,
+   * but error message generated could be less than ideal.
+   *
+   * TODO(user): we may use one factory per injector tree for optimization reasons
+   */
+  private static final CycleDetectingLockFactory<Key<?>> cycleDetectingLockFactory =
+      new CycleDetectingLockFactory<Key<?>>();
+
+  /**
+   * Provides singleton scope with the following properties:
+   * - creates no more than one instance per Key as a creator is used no more than once,
+   * - result is cached and returned quickly on subsequent calls,
+   * - exception in a creator is not treated as instance creation and is not cached,
+   * - creates singletons in parallel whenever possible,
+   * - waits for dependent singletons to be created even across threads and when dependencies
+   *   are shared as long as no circular dependencies are detected,
+   * - returns circular proxy only when circular dependencies are detected,
+   * - aside from that, blocking synchronization is only used for proxy creation and initialization,
+   * @see CycleDetectingLockFactory
+   */
+  public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator) {
+    /**
+     * Locking strategy:
+     * - volatile instance: double-checked locking for quick exit when scope is initialized,
+     * - constructionContext: manipulations with proxies list or instance initialization
+     * - creationLock: singleton instance creation,
+     *   -- allows to guarantee only one instance per singleton,
+     *   -- special type of a lock, that prevents potential deadlocks,
+     *   -- guards constructionContext for all operations except proxy creation
+     */
+    return new Provider<T>() {
+      /**
+       * The lazily initialized singleton instance. Once set, this will either have type T or will
+       * be equal to NULL. Would never be reset to null.
+       */
+      volatile Object instance;
+
+      /**
+       * Circular proxies are used when potential deadlocks are detected. Guarded by itself.
+       * ConstructionContext is not thread-safe, so each call should be synchronized.
+       */
+      final ConstructionContext<T> constructionContext = new ConstructionContext<T>();
+
+      /** For each binding there is a separate lock that we hold during object creation. */
+      final CycleDetectingLock<Key<?>> creationLock = cycleDetectingLockFactory.create(key);
+
+      @SuppressWarnings("DoubleCheckedLocking")
+      public T get() {
+        // cache volatile variable for the usual case of already initialized object
+        final Object initialInstance = instance;
+        if (initialInstance == null) {
+          // instance is not initialized yet
+
+          // acquire lock for current binding to initialize an instance
+          final ListMultimap<Long, Key<?>> locksCycle =
+              creationLock.lockOrDetectPotentialLocksCycle();
+          if (locksCycle.isEmpty()) {
+            // this thread now owns creation of an instance
+            try {
+              // intentionally reread volatile variable to prevent double initialization
+              if (instance == null) {
+                // creator throwing an exception can cause circular proxies created in
+                // different thread to never be resolved, just a warning
+                T provided = creator.get();
+                Object providedNotNull = provided == null ? NULL : provided;
+
+                // scope called recursively can initialize instance as a side effect
+                if (instance == null) {
+                  // instance is still not initialized, se we can proceed
+
+                  // don't remember proxies created by Guice on circular dependency
+                  // detection within the same thread; they are not real instances to cache
+                  if (Scopes.isCircularProxy(provided)) {
+                    return provided;
+                  }
+
+                  synchronized (constructionContext) {
+                    // guarantee thread-safety for instance and proxies initialization
+                    instance = providedNotNull;
+                    constructionContext.setProxyDelegates(provided);
+                  }
+                } else {
+                  // safety assert in case instance was initialized
+                  Preconditions.checkState(instance == providedNotNull,
+                      "Singleton is called recursively returning different results");
+                }
+              }
+            } catch (RuntimeException e) {
+              // something went wrong, be sure to clean a construction context
+              // this helps to prevent potential memory leaks in circular proxies list
+              synchronized (constructionContext) {
+                constructionContext.finishConstruction();
+              }
+              throw e;
+            } finally {
+              // always release our creation lock, even on failures
+              creationLock.unlock();
+            }
+          } else {
+            // potential deadlock detected, creation lock is not taken by this thread
+            synchronized (constructionContext) {
+              // guarantee thread-safety for instance and proxies initialization
+              if (instance == null) {
+                // InjectorImpl.callInContext() sets this context when scope is called from Guice
+                Map<Thread, InternalContext> globalInternalContext =
+                    InjectorImpl.getGlobalInternalContext();
+                InternalContext internalContext = globalInternalContext.get(Thread.currentThread());
+
+                // creating a proxy to satisfy circular dependency across several threads
+                Dependency<?> dependency = Preconditions.checkNotNull(
+                    internalContext.getDependency(),
+                    "globalInternalContext.get(currentThread()).getDependency()");
+                Class<?> rawType = dependency.getKey().getTypeLiteral().getRawType();
+
+                try {
+                  @SuppressWarnings("unchecked")
+                  T proxy = (T) constructionContext.createProxy(
+                      new Errors(), internalContext.getInjectorOptions(), rawType);
+                  return proxy;
+                } catch (ErrorsException e) {
+                  // best effort to create a rich error message
+                  List<Message> exceptionErrorMessages = e.getErrors().getMessages();
+                  // we expect an error thrown
+                  Preconditions.checkState(exceptionErrorMessages.size() == 1);
+                  // explicitly copy the map to guarantee iteration correctness
+                  // it's ok to have a data race with other threads that are locked
+                  Message cycleDependenciesMessage = createCycleDependenciesMessage(
+                      ImmutableMap.copyOf(globalInternalContext),
+                      locksCycle,
+                      exceptionErrorMessages.get(0));
+                  // adding stack trace generated by us in addition to a standard one
+                  throw new ProvisionException(ImmutableList.of(
+                      cycleDependenciesMessage, exceptionErrorMessages.get(0)));
+                }
+              }
+            }
+          }
+          // at this point we're sure that singleton was initialized,
+          // reread volatile variable to catch all corner cases
+
+          // caching volatile variable to minimize number of reads performed
+          final Object initializedInstance = instance;
+          Preconditions.checkState(initializedInstance != null,
+              "Internal error: Singleton is not initialized contrary to our expectations");
+          @SuppressWarnings("unchecked")
+          T initializedTypedInstance = (T) initializedInstance;
+          return initializedInstance == NULL ? null : initializedTypedInstance;
+        } else {
+          // singleton is already initialized and local cache can be used
+          @SuppressWarnings("unchecked")
+          T typedInitialIntance = (T) initialInstance;
+          return initialInstance == NULL ? null : typedInitialIntance;
+        }
+      }
+
+      /**
+       * Helper method to create beautiful and rich error descriptions. Best effort and slow.
+       * Tries its best to provide dependency information from injectors currently available
+       * in a global internal context.
+       *
+       * <p>The main thing being done is creating a list of Dependencies involved into
+       * lock cycle across all the threads involved. This is a structure we're creating:
+       * <pre>
+       * { Current Thread, C.class, B.class, Other Thread, B.class, C.class, Current Thread }
+       * To be inserted in the beginning by Guice: { A.class, B.class, C.class }
+       * </pre>
+       * When we're calling Guice to create A and it fails in the deadlock while trying to
+       * create C, which is being created by another thread, which waits for B. List would
+       * be reversed before printing it to the end user.
+       */
+      private Message createCycleDependenciesMessage(
+          Map<Thread, InternalContext> globalInternalContext,
+          ListMultimap<Long, Key<?>> locksCycle,
+          Message proxyCreationError) {
+        // this is the main thing that we'll show in an error message,
+        // current thread is populate by Guice
+        List<Object> sourcesCycle = Lists.newArrayList();
+        sourcesCycle.add(Thread.currentThread());
+        // temp map to speed up look ups
+        Map<Long, Thread> threadById = Maps.newHashMap();
+        for (Thread thread : globalInternalContext.keySet()) {
+          threadById.put(thread.getId(), thread);
+        }
+        for (long lockedThreadId : locksCycle.keySet()) {
+          Thread lockedThread = threadById.get(lockedThreadId);
+          List<Key<?>> lockedKeys = Collections.unmodifiableList(locksCycle.get(lockedThreadId));
+          if (lockedThread == null) {
+            // thread in a lock cycle is already terminated
+            continue;
+          }
+          List<DependencyAndSource> dependencyChain = null;
+          boolean allLockedKeysAreFoundInDependencies = false;
+          // thread in a cycle is still present
+          InternalContext lockedThreadInternalContext = globalInternalContext.get(lockedThread);
+          if (lockedThreadInternalContext != null) {
+            dependencyChain = lockedThreadInternalContext.getDependencyChain();
+
+            // check that all of the keys are still present in dependency chain in order
+            List<Key<?>> lockedKeysToFind = Lists.newLinkedList(lockedKeys);
+            // check stack trace of the thread
+            for (DependencyAndSource d : dependencyChain) {
+              Dependency<?> dependency = d.getDependency();
+              if (dependency == null) {
+                continue;
+              }
+              if (dependency.getKey().equals(lockedKeysToFind.get(0))) {
+                lockedKeysToFind.remove(0);
+                if (lockedKeysToFind.isEmpty()) {
+                  // everything is found!
+                  allLockedKeysAreFoundInDependencies = true;
+                  break;
+                }
+              }
+            }
+          }
+          if (allLockedKeysAreFoundInDependencies) {
+            // all keys are present in a dependency chain of a thread's last injector,
+            // highly likely that we just have discovered a dependency
+            // chain that is part of a lock cycle starting with the first lock owned
+            Key<?> firstLockedKey = lockedKeys.get(0);
+            boolean firstLockedKeyFound = false;
+            for (DependencyAndSource d : dependencyChain) {
+              Dependency<?> dependency = d.getDependency();
+              if (dependency == null) {
+                continue;
+              }
+              if (firstLockedKeyFound) {
+                sourcesCycle.add(dependency);
+                sourcesCycle.add(d.getBindingSource());
+              } else if (dependency.getKey().equals(firstLockedKey)) {
+                firstLockedKeyFound = true;
+                // for the very first one found we don't care why, so no dependency is added
+                sourcesCycle.add(d.getBindingSource());
+              }
+            }
+          } else {
+            // something went wrong and not all keys are present in a state of an injector
+            // that was used last for a current thread.
+            // let's add all keys we're aware of, still better than nothing
+            sourcesCycle.addAll(lockedKeys);
+          }
+          // mentions that a tread is a part of a cycle
+          sourcesCycle.add(lockedThread);
+        }
+        return new Message(
+            sourcesCycle,
+            String.format("Encountered circular dependency spanning several threads. %s",
+                proxyCreationError.getMessage()),
+            null);
+      }
+
+      @Override
+      public String toString() {
+        return String.format("%s[%s]", creator, Scopes.SINGLETON);
+      }
+    };
+  }
+
+  @Override public String toString() {
+    return "Scopes.SINGLETON";
+  }
+}
diff --git a/core/src/com/google/inject/internal/State.java b/core/src/com/google/inject/internal/State.java
new file mode 100644
index 0000000..32c2da6
--- /dev/null
+++ b/core/src/com/google/inject/internal/State.java
@@ -0,0 +1,209 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.Scope;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.ModuleAnnotatedMethodScanner;
+import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding;
+import com.google.inject.spi.ProvisionListenerBinding;
+import com.google.inject.spi.ScopeBinding;
+import com.google.inject.spi.TypeConverterBinding;
+import com.google.inject.spi.TypeListenerBinding;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The inheritable data within an injector. This class is intended to allow parent and local
+ * injector data to be accessed as a unit.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+interface State {
+
+  static final State NONE = new State() {
+    public State parent() {
+      throw new UnsupportedOperationException();
+    }
+
+    public <T> BindingImpl<T> getExplicitBinding(Key<T> key) {
+      return null;
+    }
+
+    public Map<Key<?>, Binding<?>> getExplicitBindingsThisLevel() {
+      throw new UnsupportedOperationException();
+    }
+
+    public void putBinding(Key<?> key, BindingImpl<?> binding) {
+      throw new UnsupportedOperationException();
+    }
+
+    public ScopeBinding getScopeBinding(Class<? extends Annotation> scopingAnnotation) {
+      return null;
+    }
+
+    public void putScopeBinding(Class<? extends Annotation> annotationType, ScopeBinding scope) {
+      throw new UnsupportedOperationException();
+    }
+
+    public void addConverter(TypeConverterBinding typeConverterBinding) {
+      throw new UnsupportedOperationException();
+    }
+
+    public TypeConverterBinding getConverter(String stringValue, TypeLiteral<?> type, Errors errors,
+        Object source) {
+      throw new UnsupportedOperationException();
+    }
+
+    public Iterable<TypeConverterBinding> getConvertersThisLevel() {
+      return ImmutableSet.of();
+    }
+
+    /*if[AOP]*/
+    public void addMethodAspect(MethodAspect methodAspect) {
+      throw new UnsupportedOperationException();
+    }
+
+    public ImmutableList<MethodAspect> getMethodAspects() {
+      return ImmutableList.of();
+    }
+    /*end[AOP]*/
+
+    public void addTypeListener(TypeListenerBinding typeListenerBinding) {
+      throw new UnsupportedOperationException();
+    }
+
+    public List<TypeListenerBinding> getTypeListenerBindings() {
+      return ImmutableList.of();
+    }
+    
+    public void addProvisionListener(ProvisionListenerBinding provisionListenerBinding) {
+      throw new UnsupportedOperationException();
+    }
+    
+    public List<ProvisionListenerBinding> getProvisionListenerBindings() {
+      return ImmutableList.of();
+    }
+
+    public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) {
+      throw new UnsupportedOperationException();
+    }
+
+    public List<ModuleAnnotatedMethodScannerBinding> getScannerBindings() {
+      return ImmutableList.of();
+    }
+
+    public void blacklist(Key<?> key, State state, Object source) {
+    }
+
+    public boolean isBlacklisted(Key<?> key) {
+      return true;
+    }
+    
+    public Set<Object> getSourcesForBlacklistedKey(Key<?> key) {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object lock() {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object singletonCreationLock() {
+      throw new UnsupportedOperationException();
+    }
+
+    public Map<Class<? extends Annotation>, Scope> getScopes() {
+      return ImmutableMap.of();
+    }
+  };
+
+  State parent();
+
+  /** Gets a binding which was specified explicitly in a module, or null. */
+  <T> BindingImpl<T> getExplicitBinding(Key<T> key);
+
+  /** Returns the explicit bindings at this level only. */
+  Map<Key<?>, Binding<?>> getExplicitBindingsThisLevel();
+
+  void putBinding(Key<?> key, BindingImpl<?> binding);
+ 
+  ScopeBinding getScopeBinding(Class<? extends Annotation> scopingAnnotation);
+
+  void putScopeBinding(Class<? extends Annotation> annotationType, ScopeBinding scope);
+
+  void addConverter(TypeConverterBinding typeConverterBinding);
+
+  /** Returns the matching converter for {@code type}, or null if none match. */
+  TypeConverterBinding getConverter(
+      String stringValue, TypeLiteral<?> type, Errors errors, Object source);
+
+  /** Returns all converters at this level only. */
+  Iterable<TypeConverterBinding> getConvertersThisLevel();
+
+  /*if[AOP]*/
+  void addMethodAspect(MethodAspect methodAspect);
+
+  ImmutableList<MethodAspect> getMethodAspects();
+  /*end[AOP]*/
+
+  void addTypeListener(TypeListenerBinding typeListenerBinding);
+  
+  List<TypeListenerBinding> getTypeListenerBindings();
+  
+  void addProvisionListener(ProvisionListenerBinding provisionListenerBinding);
+  
+  List<ProvisionListenerBinding> getProvisionListenerBindings();
+
+  void addScanner(ModuleAnnotatedMethodScannerBinding scanner);
+
+  List<ModuleAnnotatedMethodScannerBinding> getScannerBindings();
+
+  /**
+   * Forbids the corresponding injector from creating a binding to {@code key}. Child injectors
+   * blacklist their bound keys on their parent injectors to prevent just-in-time bindings on the
+   * parent injector that would conflict and pass along their state to control the lifetimes.
+   */
+  void blacklist(Key<?> key, State state, Object source);
+
+  /**
+   * Returns true if {@code key} is forbidden from being bound in this injector. This indicates that
+   * one of this injector's descendent's has bound the key.
+   */
+  boolean isBlacklisted(Key<?> key);
+  
+  /** Returns the source of a blacklisted key. */
+  Set<Object> getSourcesForBlacklistedKey(Key<?> key);
+
+  /**
+   * Returns the shared lock for all injector data. This is a low-granularity, high-contention lock
+   * to be used when reading mutable data (ie. just-in-time bindings, and binding blacklists).
+   */
+  Object lock();
+
+  /**
+   * Returns all the scope bindings at this level and parent levels.
+   */
+  Map<Class<? extends Annotation>, Scope> getScopes();
+}
diff --git a/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java b/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java
new file mode 100644
index 0000000..7ab52ce
--- /dev/null
+++ b/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.util.SourceProvider;
+import com.google.inject.matcher.AbstractMatcher;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.TypeConverter;
+import com.google.inject.spi.TypeConverterBinding;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+/**
+ * Handles {@code Binder.convertToTypes} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class TypeConverterBindingProcessor extends AbstractProcessor {
+
+  TypeConverterBindingProcessor(Errors errors) {
+    super(errors);
+  }
+
+  /** Installs default converters for primitives, enums, and class literals. */
+  static void prepareBuiltInConverters(InjectorImpl injector) {
+    // Configure type converters.
+    convertToPrimitiveType(injector, int.class, Integer.class);
+    convertToPrimitiveType(injector, long.class, Long.class);
+    convertToPrimitiveType(injector, boolean.class, Boolean.class);
+    convertToPrimitiveType(injector, byte.class, Byte.class);
+    convertToPrimitiveType(injector, short.class, Short.class);
+    convertToPrimitiveType(injector, float.class, Float.class);
+    convertToPrimitiveType(injector, double.class, Double.class);
+
+    convertToClass(injector, Character.class, new TypeConverter() {
+      public Object convert(String value, TypeLiteral<?> toType) {
+        value = value.trim();
+        if (value.length() != 1) {
+          throw new RuntimeException("Length != 1.");
+        }
+        return value.charAt(0);
+      }
+
+      @Override public String toString() {
+        return "TypeConverter<Character>";
+      }
+    });
+
+    convertToClasses(injector, Matchers.subclassesOf(Enum.class), new TypeConverter() {
+      @SuppressWarnings("unchecked")
+      public Object convert(String value, TypeLiteral<?> toType) {
+          return Enum.valueOf((Class) toType.getRawType(), value);
+        }
+
+        @Override public String toString() {
+          return "TypeConverter<E extends Enum<E>>";
+        }
+      });
+
+    internalConvertToTypes(injector, new AbstractMatcher<TypeLiteral<?>>() {
+        public boolean matches(TypeLiteral<?> typeLiteral) {
+          return typeLiteral.getRawType() == Class.class;
+        }
+
+        @Override public String toString() {
+          return "Class<?>";
+        }
+      },
+      new TypeConverter() {
+        @SuppressWarnings("unchecked")
+        public Object convert(String value, TypeLiteral<?> toType) {
+          try {
+            return Class.forName(value);
+          } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e.getMessage());
+          }
+        }
+
+        @Override public String toString() {
+          return "TypeConverter<Class<?>>";
+        }
+      }
+    );
+  }
+
+  private static <T> void convertToPrimitiveType(InjectorImpl injector, Class<T> primitiveType,
+      final Class<T> wrapperType) {
+    try {
+      final Method parser = wrapperType.getMethod(
+          "parse" + capitalize(primitiveType.getName()), String.class);
+
+      TypeConverter typeConverter = new TypeConverter() {
+        @SuppressWarnings("unchecked")
+        public Object convert(String value, TypeLiteral<?> toType) {
+          try {
+            return parser.invoke(null, value);
+          } catch (IllegalAccessException e) {
+            throw new AssertionError(e);
+          } catch (InvocationTargetException e) {
+            throw new RuntimeException(e.getTargetException().getMessage());
+          }
+        }
+
+        @Override public String toString() {
+          return "TypeConverter<" + wrapperType.getSimpleName() + ">";
+        }
+      };
+
+      convertToClass(injector, wrapperType, typeConverter);
+    } catch (NoSuchMethodException e) {
+      throw new AssertionError(e);
+    }
+  }
+
+  private static <T> void convertToClass(InjectorImpl injector, Class<T> type,
+      TypeConverter converter) {
+    convertToClasses(injector, Matchers.identicalTo(type), converter);
+  }
+
+  private static void convertToClasses(InjectorImpl injector,
+      final Matcher<? super Class<?>> typeMatcher, TypeConverter converter) {
+    internalConvertToTypes(injector, new AbstractMatcher<TypeLiteral<?>>() {
+      public boolean matches(TypeLiteral<?> typeLiteral) {
+        Type type = typeLiteral.getType();
+        if (!(type instanceof Class)) {
+          return false;
+        }
+        Class<?> clazz = (Class<?>) type;
+        return typeMatcher.matches(clazz);
+      }
+
+      @Override public String toString() {
+        return typeMatcher.toString();
+      }
+    }, converter);
+  }
+
+  private static void internalConvertToTypes(InjectorImpl injector,
+      Matcher<? super TypeLiteral<?>> typeMatcher,
+      TypeConverter converter) {
+    injector.state.addConverter(
+        new TypeConverterBinding(SourceProvider.UNKNOWN_SOURCE, typeMatcher, converter));
+  }
+
+  @Override public Boolean visit(TypeConverterBinding command) {
+    injector.state.addConverter(new TypeConverterBinding(
+        command.getSource(), command.getTypeMatcher(), command.getTypeConverter()));
+    return true;
+  }
+  
+  private static String capitalize(String s) {
+    if (s.length() == 0) {
+      return s;
+    }
+    char first = s.charAt(0);
+    char capitalized = Character.toUpperCase(first);
+    return (first == capitalized)
+        ? s
+        : capitalized + s.substring(1);
+  }
+
+}
diff --git a/core/src/com/google/inject/internal/UniqueAnnotations.java b/core/src/com/google/inject/internal/UniqueAnnotations.java
new file mode 100644
index 0000000..924175e
--- /dev/null
+++ b/core/src/com/google/inject/internal/UniqueAnnotations.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class UniqueAnnotations {
+  private UniqueAnnotations() {}
+  private static final AtomicInteger nextUniqueValue = new AtomicInteger(1);
+
+  /**
+   * Returns an annotation instance that is not equal to any other annotation
+   * instances, for use in creating distinct {@link com.google.inject.Key}s.
+   */
+  public static Annotation create() {
+    return create(nextUniqueValue.getAndIncrement());
+  }
+
+  static Annotation create(final int value) {
+    return new Internal() {
+      public int value() {
+        return value;
+      }
+
+      public Class<? extends Annotation> annotationType() {
+        return Internal.class;
+      }
+
+      @Override public String toString() {
+        return "@" + Internal.class.getName() + "(value=" + value + ")";
+      }
+
+      @Override public boolean equals(Object o) {
+        return o instanceof Internal
+            && ((Internal) o).value() == value();
+      }
+
+      @Override public int hashCode() {
+        return (127 * "value".hashCode()) ^ value;
+      }
+    };
+  }
+
+  @Retention(RUNTIME) @BindingAnnotation
+  @interface Internal {
+    int value();
+  }
+}
diff --git a/core/src/com/google/inject/internal/UntargettedBindingImpl.java b/core/src/com/google/inject/internal/UntargettedBindingImpl.java
new file mode 100644
index 0000000..a2d3365
--- /dev/null
+++ b/core/src/com/google/inject/internal/UntargettedBindingImpl.java
@@ -0,0 +1,78 @@
+/*
+ * 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 com.google.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.UntargettedBinding;
+
+final class UntargettedBindingImpl<T> extends BindingImpl<T> implements UntargettedBinding<T> {
+
+  UntargettedBindingImpl(InjectorImpl injector, Key<T> key, Object source) {
+    super(injector, key, source, new InternalFactory<T>() {
+      public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) {
+        throw new AssertionError();
+      }
+    }, Scoping.UNSCOPED);
+  }
+
+  public UntargettedBindingImpl(Object source, Key<T> key, Scoping scoping) {
+    super(source, key, scoping);
+  }
+
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
+    return visitor.visit(this);
+  }
+
+  public BindingImpl<T> withScoping(Scoping scoping) {
+    return new UntargettedBindingImpl<T>(getSource(), getKey(), scoping);
+  }
+
+  public BindingImpl<T> withKey(Key<T> key) {
+    return new UntargettedBindingImpl<T>(getSource(), key, getScoping());
+  }
+
+  public void applyTo(Binder binder) {
+    getScoping().applyTo(binder.withSource(getSource()).bind(getKey()));
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(UntargettedBinding.class)
+        .add("key", getKey())
+        .add("source", getSource())
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if(obj instanceof UntargettedBindingImpl) {
+      UntargettedBindingImpl<?> o = (UntargettedBindingImpl<?>)obj;
+      return getKey().equals(o.getKey())
+        && getScoping().equals(o.getScoping());
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(getKey(), getScoping());
+  }
+}
diff --git a/core/src/com/google/inject/internal/UntargettedBindingProcessor.java b/core/src/com/google/inject/internal/UntargettedBindingProcessor.java
new file mode 100644
index 0000000..8ca2ecc
--- /dev/null
+++ b/core/src/com/google/inject/internal/UntargettedBindingProcessor.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.internal;
+
+import com.google.inject.Binding;
+import com.google.inject.spi.UntargettedBinding;
+
+/**
+ * Processes just UntargettedBindings.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+class UntargettedBindingProcessor extends AbstractBindingProcessor {
+  
+  UntargettedBindingProcessor(Errors errors, ProcessedBindingData bindingData) {
+    super(errors, bindingData);
+  }
+  
+  @Override
+  public <T> Boolean visit(Binding<T> binding) {
+    return binding.acceptTargetVisitor(new Processor<T, Boolean>((BindingImpl<T>)binding) {  
+      public Boolean visit(UntargettedBinding<? extends T> untargetted) {
+        prepareBinding();
+
+        // Error: Missing implementation.
+        // Example: bind(Date.class).annotatedWith(Red.class);
+        // We can't assume abstract types aren't injectable. They may have an
+        // @ImplementedBy annotation or something.
+        if (key.getAnnotationType() != null) {
+          errors.missingImplementation(key);
+          putBinding(invalidBinding(injector, key, source));
+          return true;
+        }
+    
+        // This cast is safe after the preceeding check.
+        try {
+          BindingImpl<T> binding = injector.createUninitializedBinding(
+              key, scoping, source, errors, false);
+          scheduleInitialization(binding);
+          putBinding(binding);
+        } catch (ErrorsException e) {
+          errors.merge(e.getErrors());
+          putBinding(invalidBinding(injector, key, source));
+        }
+    
+        return true;
+      }
+      
+      @Override
+      protected Boolean visitOther(Binding<? extends T> binding) {
+        return false;
+      }
+    });
+  }
+}
diff --git a/core/src/com/google/inject/internal/WeakKeySet.java b/core/src/com/google/inject/internal/WeakKeySet.java
new file mode 100644
index 0000000..ca137df
--- /dev/null
+++ b/core/src/com/google/inject/internal/WeakKeySet.java
@@ -0,0 +1,157 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
+import com.google.common.collect.LinkedHashMultiset;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Sets;
+import com.google.inject.Key;
+import com.google.inject.internal.util.SourceProvider;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Minimal set that doesn't hold strong references to the contained keys.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class WeakKeySet {
+
+  private Map<Key<?>, Multiset<Object>> backingMap;
+
+  /**
+   * This is already locked externally on add and getSources but we need it to handle clean up in
+   * the evictionCache's RemovalListener.
+   */
+  private final Object lock;
+
+  /**
+   * Tracks child injector lifetimes and evicts blacklisted keys/sources after the child injector is
+   * garbage collected.
+   */
+  private final Cache<State, Set<KeyAndSource>> evictionCache = CacheBuilder.newBuilder()
+      .weakKeys()
+      .removalListener(
+          new RemovalListener<State, Set<KeyAndSource>>() {
+            @Override
+            public void onRemoval(RemovalNotification<State, Set<KeyAndSource>> notification) {
+              Preconditions.checkState(RemovalCause.COLLECTED.equals(notification.getCause()));
+
+              cleanUpForCollectedState(notification.getValue());
+            }
+          })
+      .build();
+
+  /**
+   * There may be multiple child injectors blacklisting a certain key so only remove the source
+   * that's relevant.
+   */
+  private void cleanUpForCollectedState(Set<KeyAndSource> keysAndSources) {
+    synchronized (lock) {
+      for (KeyAndSource keyAndSource : keysAndSources) {
+        Multiset<Object> set = backingMap.get(keyAndSource.key);
+        if (set != null) {
+          set.remove(keyAndSource.source);
+          if (set.isEmpty()) {
+            backingMap.remove(keyAndSource.key);
+          }
+        }
+      }
+    }
+  }
+
+  WeakKeySet(Object lock) {
+    this.lock = lock;
+  }
+
+  public void add(Key<?> key, State state, Object source) {
+    if (backingMap == null) {
+      backingMap = Maps.newHashMap();
+    }
+    // if it's an instanceof Class, it was a JIT binding, which we don't
+    // want to retain.
+    if (source instanceof Class || source == SourceProvider.UNKNOWN_SOURCE) {
+      source = null;
+    }
+    Multiset<Object> sources = backingMap.get(key);
+    if (sources == null) {
+      sources = LinkedHashMultiset.create();
+      backingMap.put(key, sources);
+    }
+    Object convertedSource = Errors.convert(source);
+    sources.add(convertedSource);
+
+    // Avoid all the extra work if we can.
+    if (state.parent() != State.NONE) {
+      Set<KeyAndSource> keyAndSources = evictionCache.getIfPresent(state);
+      if (keyAndSources == null) {
+        evictionCache.put(state, keyAndSources = Sets.newHashSet());
+      }
+      keyAndSources.add(new KeyAndSource(key, convertedSource));
+    }
+  }
+
+  public boolean contains(Key<?> key) {
+    evictionCache.cleanUp();
+    return backingMap != null && backingMap.containsKey(key);
+  }
+
+  public Set<Object> getSources(Key<?> key) {
+    evictionCache.cleanUp();
+    Multiset<Object> sources = (backingMap == null) ? null : backingMap.get(key);
+    return (sources == null) ? null : sources.elementSet();
+  }
+
+  private static final class KeyAndSource {
+    final Key<?> key;
+    final Object source;
+
+    KeyAndSource(Key<?> key, Object source) {
+      this.key = key;
+      this.source = source;
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hashCode(key, source);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj) {
+        return true;
+      }
+
+      if (!(obj instanceof KeyAndSource)) {
+        return false;
+      }
+
+      KeyAndSource other = (KeyAndSource) obj;
+      return Objects.equal(key, other.key)
+          && Objects.equal(source, other.source);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/package-info.java b/core/src/com/google/inject/internal/package-info.java
new file mode 100644
index 0000000..4116f11
--- /dev/null
+++ b/core/src/com/google/inject/internal/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * <i>Guice</i> (sounds like like "juice")
+ */
+package com.google.inject.internal;
diff --git a/core/src/com/google/inject/internal/util/Classes.java b/core/src/com/google/inject/internal/util/Classes.java
new file mode 100644
index 0000000..0badab1
--- /dev/null
+++ b/core/src/com/google/inject/internal/util/Classes.java
@@ -0,0 +1,80 @@
+/**
+ * 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 com.google.inject.internal.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Class utilities.
+ */
+public final class Classes {
+
+  public static boolean isInnerClass(Class<?> clazz) {
+    return !Modifier.isStatic(clazz.getModifiers())
+        && clazz.getEnclosingClass() != null;
+  }
+
+  public static boolean isConcrete(Class<?> clazz) {
+    int modifiers = clazz.getModifiers();
+    return !clazz.isInterface() && !Modifier.isAbstract(modifiers);
+  }
+
+  /**
+   * Formats a member as concise string, such as {@code java.util.ArrayList.size},
+   * {@code java.util.ArrayList<init>()} or {@code java.util.List.remove()}.
+   */
+  public static String toString(Member member) {
+    Class<? extends Member> memberType = Classes.memberType(member);
+  
+    if (memberType == Method.class) {
+      return member.getDeclaringClass().getName() + "." + member.getName() + "()";
+    } else if (memberType == Field.class) {
+      return member.getDeclaringClass().getName() + "." + member.getName();
+    } else if (memberType == Constructor.class) {
+      return member.getDeclaringClass().getName() + ".<init>()";
+    } else {
+      throw new AssertionError();
+    }
+  }
+
+  /**
+   * Returns {@code Field.class}, {@code Method.class} or {@code Constructor.class}.
+   */
+  public static Class<? extends Member> memberType(Member member) {
+    checkNotNull(member, "member");
+  
+    if (member instanceof Field) {
+      return Field.class;
+  
+    } else if (member instanceof Method) {
+      return Method.class;
+  
+    } else if (member instanceof Constructor) {
+      return Constructor.class;
+  
+    } else {
+      throw new IllegalArgumentException(
+          "Unsupported implementation class for Member, " + member.getClass());
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/util/LineNumbers.java b/core/src/com/google/inject/internal/util/LineNumbers.java
new file mode 100644
index 0000000..57c98b9
--- /dev/null
+++ b/core/src/com/google/inject/internal/util/LineNumbers.java
@@ -0,0 +1,223 @@
+/**
+ * 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 com.google.inject.internal.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+/**
+ * Looks up line numbers for classes and their members.
+ *
+ * @author Chris Nokleberg
+ */
+final class LineNumbers {
+
+  private final Class type;
+  private final Map<String, Integer> lines = Maps.newHashMap();
+  private String source;
+  private int firstLine = Integer.MAX_VALUE;
+
+  /**
+   * Reads line number information from the given class, if available.
+   *
+   * @param type the class to read line number information from
+   * @throws IllegalArgumentException if the bytecode for the class cannot be found
+   * @throws java.io.IOException if an error occurs while reading bytecode
+   */
+  public LineNumbers(Class type) throws IOException {
+    this.type = type;
+
+    if (!type.isArray()) {
+      InputStream in = type.getResourceAsStream("/" + type.getName().replace('.', '/') + ".class");
+      if (in != null) {
+        new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES);
+      }
+    }
+  }
+
+  /**
+   * Get the source file name as read from the bytecode.
+   *
+   * @return the source file name if available, or null
+   */
+  public String getSource() {
+    return source;
+  }
+
+  /**
+   * Get the line number associated with the given member.
+   *
+   * @param member a field, constructor, or method belonging to the class used during construction
+   * @return the wrapped line number, or null if not available
+   * @throws IllegalArgumentException if the member does not belong to the class used during
+   * construction
+   */
+  public Integer getLineNumber(Member member) {
+    Preconditions.checkArgument(type == member.getDeclaringClass(),
+        "Member %s belongs to %s, not %s", member, member.getDeclaringClass(), type);
+    return lines.get(memberKey(member));
+  }
+
+  /** Gets the first line number. */
+  public int getFirstLine() {
+    return firstLine == Integer.MAX_VALUE ? 1 : firstLine;
+  }
+
+  private String memberKey(Member member) {
+    checkNotNull(member, "member");
+
+    /*if[AOP]*/
+    if (member instanceof Field) {
+      return member.getName();
+
+    } else if (member instanceof Method) {
+      return member.getName() + org.objectweb.asm.Type.getMethodDescriptor((Method) member);
+
+    } else if (member instanceof Constructor) {
+      StringBuilder sb = new StringBuilder().append("<init>(");
+      for (Class param : ((Constructor) member).getParameterTypes()) {
+          sb.append(org.objectweb.asm.Type.getDescriptor(param));
+      }
+      return sb.append(")V").toString();
+
+    } else {
+      throw new IllegalArgumentException(
+          "Unsupported implementation class for Member, " + member.getClass());
+    }
+    /*end[AOP]*/
+    /*if[NO_AOP]
+    return "<NO_MEMBER_KEY>";
+    end[NO_AOP]*/
+  }  
+
+  private class LineNumberReader extends ClassVisitor {
+
+    private int line = -1;
+    private String pendingMethod;
+    private String name;
+
+    LineNumberReader() {
+      super(Opcodes.ASM5);
+    }
+
+    public void visit(int version, int access, String name, String signature,
+        String superName, String[] interfaces) {
+      this.name = name;
+    }
+
+    public MethodVisitor visitMethod(int access, String name, String desc,
+        String signature, String[] exceptions) {
+      if ((access & Opcodes.ACC_PRIVATE) != 0) {
+        return null;
+      }
+      pendingMethod = name + desc;
+      line = -1;
+      return new LineNumberMethodVisitor();
+    }
+
+    public void visitSource(String source, String debug) {
+      LineNumbers.this.source = source;
+    }
+
+    public void visitLineNumber(int line, Label start) {
+      if (line < firstLine) {
+        firstLine = line;
+      }
+
+      this.line = line;
+      if (pendingMethod != null) {
+        lines.put(pendingMethod, line);
+        pendingMethod = null;
+      }
+    }
+
+    public FieldVisitor visitField(int access, String name, String desc,
+        String signature, Object value) {
+      return null;
+    }
+
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+      return new LineNumberAnnotationVisitor();
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(int parameter,
+        String desc, boolean visible) {
+      return new LineNumberAnnotationVisitor();
+    }
+
+    class LineNumberMethodVisitor extends MethodVisitor {
+      LineNumberMethodVisitor() {
+        super(Opcodes.ASM5);
+      }
+
+      public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        return new LineNumberAnnotationVisitor();
+      }
+
+      public AnnotationVisitor visitAnnotationDefault() {
+        return new LineNumberAnnotationVisitor();
+      }
+
+      public void visitFieldInsn(int opcode, String owner, String name,
+          String desc) {
+        if (opcode == Opcodes.PUTFIELD && LineNumberReader.this.name.equals(owner)
+            && !lines.containsKey(name) && line != -1) {
+          lines.put(name, line);
+        }
+      }
+
+      public void visitLineNumber(int line, Label start) {
+        LineNumberReader.this.visitLineNumber(line, start);
+      }
+    }
+
+    class LineNumberAnnotationVisitor extends AnnotationVisitor {
+      LineNumberAnnotationVisitor() {
+        super(Opcodes.ASM5);
+      }
+      public AnnotationVisitor visitAnnotation(String name, String desc) {
+        return this;
+      }
+      public AnnotationVisitor visitArray(String name) {
+        return this;
+      }
+      public void visitLocalVariable(String name, String desc, String signature,
+          Label start, Label end, int index) {
+      }
+
+    }
+
+  }
+}
diff --git a/core/src/com/google/inject/internal/util/SourceProvider.java b/core/src/com/google/inject/internal/util/SourceProvider.java
new file mode 100644
index 0000000..9d4b9f9
--- /dev/null
+++ b/core/src/com/google/inject/internal/util/SourceProvider.java
@@ -0,0 +1,105 @@
+/**
+ * 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 com.google.inject.internal.util;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+/**
+ * Provides access to the calling line of code.
+ * 
+ * @author crazybob@google.com (Bob Lee)
+ */
+public final class SourceProvider {
+
+  /** Indicates that the source is unknown. */
+  public static final Object UNKNOWN_SOURCE = "[unknown source]";
+
+  private final SourceProvider parent;
+  private final ImmutableSet<String> classNamesToSkip;
+  
+  public static final SourceProvider DEFAULT_INSTANCE
+      = new SourceProvider(ImmutableSet.of(SourceProvider.class.getName()));
+
+  private SourceProvider(Iterable<String> classesToSkip) {
+    this(null, classesToSkip);
+  }
+
+  private SourceProvider(SourceProvider parent, Iterable<String> classesToSkip) {
+    this.parent = parent;
+    
+    ImmutableSet.Builder<String> classNamesToSkipBuilder = ImmutableSet.builder();
+    for (String classToSkip : classesToSkip) {
+      if (parent == null || !parent.shouldBeSkipped(classToSkip)) {
+        classNamesToSkipBuilder.add(classToSkip);
+      }
+    }
+    this.classNamesToSkip = classNamesToSkipBuilder.build();
+  }
+
+  /** Returns a new instance that also skips {@code moreClassesToSkip}. */
+  public SourceProvider plusSkippedClasses(Class... moreClassesToSkip) {
+    return new SourceProvider(this, asStrings(moreClassesToSkip));
+  }
+
+  /** Returns true if the className should be skipped. */
+  private boolean shouldBeSkipped(String className) {
+    return (parent != null && parent.shouldBeSkipped(className))
+        || classNamesToSkip.contains(className);
+  }
+  
+  /** Returns the class names as Strings */
+  private static List<String> asStrings(Class... classes) {
+    List<String> strings = Lists.newArrayList();
+    for (Class c : classes) {
+      strings.add(c.getName());
+    }
+    return strings;
+  }
+
+  /**
+   * Returns the calling line of code. The selected line is the nearest to the top of the stack that
+   * is not skipped.
+   */
+  public StackTraceElement get(StackTraceElement[] stackTraceElements) {
+    Preconditions.checkNotNull(stackTraceElements, "The stack trace elements cannot be null.");
+    for (final StackTraceElement element : stackTraceElements) {
+      String className = element.getClassName();
+      
+      if (!shouldBeSkipped(className)) {
+        return element;
+      }
+    }
+    throw new AssertionError();
+  }
+
+  /**
+   * Returns the non-skipped module class name.
+   */
+  public Object getFromClassNames(List<String> moduleClassNames) {
+    Preconditions.checkNotNull(moduleClassNames, "The list of module class names cannot be null.");
+    for (final String moduleClassName : moduleClassNames) {
+      if (!shouldBeSkipped(moduleClassName)) {
+        return new StackTraceElement(moduleClassName, "configure", null, -1);
+      }
+    }
+    return UNKNOWN_SOURCE;
+  }
+}
diff --git a/core/src/com/google/inject/internal/util/StackTraceElements.java b/core/src/com/google/inject/internal/util/StackTraceElements.java
new file mode 100644
index 0000000..69f930f
--- /dev/null
+++ b/core/src/com/google/inject/internal/util/StackTraceElements.java
@@ -0,0 +1,218 @@
+/**
+ * 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 com.google.inject.internal.util;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.MapMaker;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.util.Map;
+
+/**
+ * Creates stack trace elements for members.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class StackTraceElements {
+
+  private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
+  private static final InMemoryStackTraceElement[] EMPTY_INMEMORY_STACK_TRACE = 
+      new InMemoryStackTraceElement[0];
+
+  /*if[AOP]*/
+  static final LoadingCache<Class<?>, LineNumbers> lineNumbersCache =
+      CacheBuilder.newBuilder().weakKeys().softValues().build(
+          new CacheLoader<Class<?>, LineNumbers>() {
+            public LineNumbers load(Class<?> key) {
+              try {
+                return new LineNumbers(key);
+              }
+              catch (IOException e) {
+                throw new RuntimeException(e);
+              }
+            }
+          });
+  /*end[AOP]*/
+
+  private static Map<Object, Object> cache = new MapMaker().makeMap();
+  private static final String UNKNOWN_SOURCE = "Unknown Source";
+
+  public static Object forMember(Member member) {
+    if (member == null) {
+      return SourceProvider.UNKNOWN_SOURCE;
+    }
+
+    Class declaringClass = member.getDeclaringClass();
+
+    /*if[AOP]*/
+    LineNumbers lineNumbers = lineNumbersCache.getUnchecked(declaringClass);
+    String fileName = lineNumbers.getSource();
+    Integer lineNumberOrNull = lineNumbers.getLineNumber(member);
+    int lineNumber = lineNumberOrNull == null ? lineNumbers.getFirstLine() : lineNumberOrNull;
+    /*end[AOP]*/
+    /*if[NO_AOP]
+    String fileName = null;
+    int lineNumber = -1;
+    end[NO_AOP]*/
+
+    Class<? extends Member> memberType = Classes.memberType(member);
+    String memberName = memberType == Constructor.class ? "<init>" : member.getName();
+    return new StackTraceElement(declaringClass.getName(), memberName, fileName, lineNumber);
+  }
+
+  public static Object forType(Class<?> implementation) {
+    /*if[AOP]*/
+    LineNumbers lineNumbers = lineNumbersCache.getUnchecked(implementation);
+    int lineNumber = lineNumbers.getFirstLine();
+    String fileName = lineNumbers.getSource();
+    /*end[AOP]*/
+    /*if[NO_AOP]
+    String fileName = null;
+    int lineNumber = -1;
+    end[NO_AOP]*/
+
+    return new StackTraceElement(implementation.getName(), "class", fileName, lineNumber);
+  }
+  
+  /**
+   * Clears the internal cache for {@link StackTraceElement StackTraceElements}.
+   */
+  public static void clearCache() {
+    cache.clear();
+  }
+  
+  /**
+   * Returns encoded in-memory version of {@link StackTraceElement StackTraceElements}.
+   */
+  public static InMemoryStackTraceElement[] convertToInMemoryStackTraceElement(
+      StackTraceElement[] stackTraceElements) {
+    if (stackTraceElements.length == 0) {
+      return EMPTY_INMEMORY_STACK_TRACE;
+    }
+    InMemoryStackTraceElement[] inMemoryStackTraceElements = 
+        new InMemoryStackTraceElement[stackTraceElements.length];
+    for (int i = 0; i < stackTraceElements.length; i++) {
+      inMemoryStackTraceElements[i] = 
+          weakIntern(new InMemoryStackTraceElement(stackTraceElements[i]));
+    }
+    return inMemoryStackTraceElements;
+  }
+  
+  /**
+   * Decodes in-memory stack trace elements to regular {@link StackTraceElement StackTraceElements}.
+   */
+  public static StackTraceElement[] convertToStackTraceElement(
+      InMemoryStackTraceElement[] inMemoryStackTraceElements) {
+    if (inMemoryStackTraceElements.length == 0) {
+      return EMPTY_STACK_TRACE;
+    }
+    StackTraceElement[] stackTraceElements = 
+        new StackTraceElement[inMemoryStackTraceElements.length];
+    for (int i = 0; i < inMemoryStackTraceElements.length; i++) {
+      String declaringClass = inMemoryStackTraceElements[i].getClassName();
+      String methodName = inMemoryStackTraceElements[i].getMethodName();
+      int lineNumber = inMemoryStackTraceElements[i].getLineNumber();
+      stackTraceElements[i] = 
+          new StackTraceElement(declaringClass, methodName, UNKNOWN_SOURCE, lineNumber);
+    }
+    return stackTraceElements;
+  }
+  
+  private static InMemoryStackTraceElement weakIntern(
+      InMemoryStackTraceElement inMemoryStackTraceElement) {
+    InMemoryStackTraceElement cached = 
+        (InMemoryStackTraceElement) cache.get(inMemoryStackTraceElement);
+    if (cached != null) {
+      return cached;
+    }
+    inMemoryStackTraceElement = new InMemoryStackTraceElement(
+        weakIntern(inMemoryStackTraceElement.getClassName()), 
+        weakIntern(inMemoryStackTraceElement.getMethodName()), 
+        inMemoryStackTraceElement.getLineNumber());
+    cache.put(inMemoryStackTraceElement, inMemoryStackTraceElement);
+    return inMemoryStackTraceElement;
+  }
+  
+  private static String weakIntern(String s) {
+    String cached = (String) cache.get(s);
+    if (cached != null) {
+      return cached;
+    }
+    cache.put(s, s);
+    return s;  
+  }
+  
+  /**
+   * In-Memory version of {@link StackTraceElement} that does not store the file name. 
+   */
+  public static class InMemoryStackTraceElement {
+    private String declaringClass;
+    private String methodName;
+    private int lineNumber;
+
+    InMemoryStackTraceElement(StackTraceElement ste) {
+      this(ste.getClassName(), ste.getMethodName(), ste.getLineNumber());
+    }
+
+    InMemoryStackTraceElement(String declaringClass, String methodName, int lineNumber) {
+      this.declaringClass = declaringClass;
+      this.methodName = methodName;
+      this.lineNumber = lineNumber;
+    }
+
+    String getClassName() {
+      return declaringClass;
+    }
+    
+    String getMethodName() {
+      return methodName;
+    }
+    
+    int getLineNumber() {
+      return lineNumber;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if (obj == this) {
+        return true;
+      }
+      if (!(obj instanceof InMemoryStackTraceElement)) {
+        return false;
+      }
+      InMemoryStackTraceElement e = (InMemoryStackTraceElement) obj;
+      return e.declaringClass.equals(declaringClass) && e.lineNumber == lineNumber && 
+          methodName.equals(e.methodName);
+    }
+
+    @Override
+    public int hashCode() {
+      int result = 31 * declaringClass.hashCode() + methodName.hashCode();
+      result = 31 * result + lineNumber;
+      return result;
+    }
+    
+    @Override
+    public String toString() {
+      return declaringClass + "." + methodName + "(" + lineNumber + ")";
+    }
+  }
+}
diff --git a/core/src/com/google/inject/internal/util/Stopwatch.java b/core/src/com/google/inject/internal/util/Stopwatch.java
new file mode 100644
index 0000000..92c73fb
--- /dev/null
+++ b/core/src/com/google/inject/internal/util/Stopwatch.java
@@ -0,0 +1,49 @@
+/**
+ * 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 com.google.inject.internal.util;
+
+import java.util.logging.Logger;
+
+/**
+ * Enables simple performance monitoring.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public final class Stopwatch {
+  private static final Logger logger = Logger.getLogger(Stopwatch.class.getName());
+
+  private long start = System.currentTimeMillis();
+
+  /**
+   * Resets and returns elapsed time in milliseconds.
+   */
+  public long reset() {
+    long now = System.currentTimeMillis();
+    try {
+      return now - start;
+    } finally {
+      start = now;
+    }
+  }
+
+  /**
+   * Resets and logs elapsed time in milliseconds.
+   */
+  public void resetAndLog(String label) {
+    logger.fine(label + ": " + reset() + "ms");
+  }
+}
diff --git a/core/src/com/google/inject/matcher/AbstractMatcher.java b/core/src/com/google/inject/matcher/AbstractMatcher.java
new file mode 100644
index 0000000..91ea2e6
--- /dev/null
+++ b/core/src/com/google/inject/matcher/AbstractMatcher.java
@@ -0,0 +1,93 @@
+/**
+ * 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 com.google.inject.matcher;
+
+import java.io.Serializable;
+
+/**
+ * Implements {@code and()} and {@code or()}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public abstract class AbstractMatcher<T> implements Matcher<T> {
+
+  public Matcher<T> and(final Matcher<? super T> other) {
+    return new AndMatcher<T>(this, other);
+  }
+
+  public Matcher<T> or(Matcher<? super T> other) {
+    return new OrMatcher<T>(this, other);
+  }
+
+  private static class AndMatcher<T> extends AbstractMatcher<T> implements Serializable {
+    private final Matcher<? super T> a, b;
+
+    public AndMatcher(Matcher<? super T> a, Matcher<? super T> b) {
+      this.a = a;
+      this.b = b;
+    }
+
+    public boolean matches(T t) {
+      return a.matches(t) && b.matches(t);
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof AndMatcher
+          && ((AndMatcher) other).a.equals(a)
+          && ((AndMatcher) other).b.equals(b);
+    }
+
+    @Override public int hashCode() {
+      return 41 * (a.hashCode() ^ b.hashCode());
+    }
+
+    @Override public String toString() {
+      return "and(" + a + ", " + b + ")";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  private static class OrMatcher<T> extends AbstractMatcher<T> implements Serializable {
+    private final Matcher<? super T> a, b;
+
+    public OrMatcher(Matcher<? super T> a, Matcher<? super T> b) {
+      this.a = a;
+      this.b = b;
+    }
+
+    public boolean matches(T t) {
+      return a.matches(t) || b.matches(t);
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof OrMatcher
+          && ((OrMatcher) other).a.equals(a)
+          && ((OrMatcher) other).b.equals(b);
+    }
+
+    @Override public int hashCode() {
+      return 37 * (a.hashCode() ^ b.hashCode());
+    }
+
+    @Override public String toString() {
+      return "or(" + a + ", " + b + ")";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+}
diff --git a/core/src/com/google/inject/matcher/Matcher.java b/core/src/com/google/inject/matcher/Matcher.java
new file mode 100644
index 0000000..681f125
--- /dev/null
+++ b/core/src/com/google/inject/matcher/Matcher.java
@@ -0,0 +1,42 @@
+/**
+ * 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 com.google.inject.matcher;
+
+/**
+ * Returns {@code true} or {@code false} for a given input.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public interface Matcher<T> {
+
+  /**
+   * Returns {@code true} if this matches {@code t}, {@code false} otherwise.
+   */
+  boolean matches(T t);
+
+  /**
+   * Returns a new matcher which returns {@code true} if both this and the
+   * given matcher return {@code true}.
+   */
+  Matcher<T> and(Matcher<? super T> other);
+
+  /**
+   * Returns a new matcher which returns {@code true} if either this or the
+   * given matcher return {@code true}.
+   */
+  Matcher<T> or(Matcher<? super T> other);
+}
diff --git a/core/src/com/google/inject/matcher/Matchers.java b/core/src/com/google/inject/matcher/Matchers.java
new file mode 100644
index 0000000..1bebcdb
--- /dev/null
+++ b/core/src/com/google/inject/matcher/Matchers.java
@@ -0,0 +1,400 @@
+/**
+ * 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 com.google.inject.matcher;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+
+/**
+ * Matcher implementations. Supports matching classes and methods.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class Matchers {
+  private Matchers() {}
+
+  /**
+   * Returns a matcher which matches any input.
+   */
+  public static Matcher<Object> any() {
+    return ANY;
+  }
+
+  private static final Matcher<Object> ANY = new Any();
+
+  private static class Any extends AbstractMatcher<Object> implements Serializable {
+    public boolean matches(Object o) {
+      return true;
+    }
+
+    @Override public String toString() {
+      return "any()";
+    }
+
+    public Object readResolve() {
+      return any();
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Inverts the given matcher.
+   */
+  public static <T> Matcher<T> not(final Matcher<? super T> p) {
+    return new Not<T>(p);
+  }
+
+  private static class Not<T> extends AbstractMatcher<T> implements Serializable {
+    final Matcher<? super T> delegate;
+
+    private Not(Matcher<? super T> delegate) {
+      this.delegate = checkNotNull(delegate, "delegate");
+    }
+
+    public boolean matches(T t) {
+      return !delegate.matches(t);
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof Not
+          && ((Not) other).delegate.equals(delegate);
+    }
+
+    @Override public int hashCode() {
+      return -delegate.hashCode();
+    }
+
+    @Override public String toString() {
+      return "not(" + delegate + ")";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  private static void checkForRuntimeRetention(
+      Class<? extends Annotation> annotationType) {
+    Retention retention = annotationType.getAnnotation(Retention.class);
+    checkArgument(retention != null && retention.value() == RetentionPolicy.RUNTIME,
+        "Annotation %s is missing RUNTIME retention", annotationType.getSimpleName());
+  }
+
+  /**
+   * Returns a matcher which matches elements (methods, classes, etc.)
+   * with a given annotation.
+   */
+  public static Matcher<AnnotatedElement> annotatedWith(
+      final Class<? extends Annotation> annotationType) {
+    return new AnnotatedWithType(annotationType);
+  }
+
+  private static class AnnotatedWithType extends AbstractMatcher<AnnotatedElement>
+      implements Serializable {
+    private final Class<? extends Annotation> annotationType;
+
+    public AnnotatedWithType(Class<? extends Annotation> annotationType) {
+      this.annotationType = checkNotNull(annotationType, "annotation type");
+      checkForRuntimeRetention(annotationType);
+    }
+
+    public boolean matches(AnnotatedElement element) {
+      return element.isAnnotationPresent(annotationType);
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof AnnotatedWithType
+          && ((AnnotatedWithType) other).annotationType.equals(annotationType);
+    }
+
+    @Override public int hashCode() {
+      return 37 * annotationType.hashCode();
+    }
+
+    @Override public String toString() {
+      return "annotatedWith(" + annotationType.getSimpleName() + ".class)";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Returns a matcher which matches elements (methods, classes, etc.)
+   * with a given annotation.
+   */
+  public static Matcher<AnnotatedElement> annotatedWith(
+      final Annotation annotation) {
+    return new AnnotatedWith(annotation);
+  }
+
+  private static class AnnotatedWith extends AbstractMatcher<AnnotatedElement>
+      implements Serializable {
+    private final Annotation annotation;
+
+    public AnnotatedWith(Annotation annotation) {
+      this.annotation = checkNotNull(annotation, "annotation");
+      checkForRuntimeRetention(annotation.annotationType());
+    }
+
+    public boolean matches(AnnotatedElement element) {
+      Annotation fromElement = element.getAnnotation(annotation.annotationType());
+      return fromElement != null && annotation.equals(fromElement);
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof AnnotatedWith
+          && ((AnnotatedWith) other).annotation.equals(annotation);
+    }
+
+    @Override public int hashCode() {
+      return 37 * annotation.hashCode();
+    }
+
+    @Override public String toString() {
+      return "annotatedWith(" + annotation + ")";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Returns a matcher which matches subclasses of the given type (as well as
+   * the given type).
+   */
+  public static Matcher<Class> subclassesOf(final Class<?> superclass) {
+    return new SubclassesOf(superclass);
+  }
+
+  private static class SubclassesOf extends AbstractMatcher<Class>
+      implements Serializable {
+    private final Class<?> superclass;
+
+    public SubclassesOf(Class<?> superclass) {
+      this.superclass = checkNotNull(superclass, "superclass");
+    }
+
+    public boolean matches(Class subclass) {
+      return superclass.isAssignableFrom(subclass);
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof SubclassesOf
+          && ((SubclassesOf) other).superclass.equals(superclass);
+    }
+
+    @Override public int hashCode() {
+      return 37 * superclass.hashCode();
+    }
+
+    @Override public String toString() {
+      return "subclassesOf(" + superclass.getSimpleName() + ".class)";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Returns a matcher which matches objects equal to the given object.
+   */
+  public static Matcher<Object> only(Object value) {
+    return new Only(value);
+  }
+
+  private static class Only extends AbstractMatcher<Object>
+      implements Serializable {
+    private final Object value;
+
+    public Only(Object value) {
+      this.value = checkNotNull(value, "value");
+    }
+
+    public boolean matches(Object other) {
+      return value.equals(other);
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof Only
+          && ((Only) other).value.equals(value);
+    }
+
+    @Override public int hashCode() {
+      return 37 * value.hashCode();
+    }
+
+    @Override public String toString() {
+      return "only(" + value + ")";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Returns a matcher which matches only the given object.
+   */
+  public static Matcher<Object> identicalTo(final Object value) {
+    return new IdenticalTo(value);
+  }
+
+  private static class IdenticalTo extends AbstractMatcher<Object>
+      implements Serializable {
+    private final Object value;
+
+    public IdenticalTo(Object value) {
+      this.value = checkNotNull(value, "value");
+    }
+
+    public boolean matches(Object other) {
+      return value == other;
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof IdenticalTo
+          && ((IdenticalTo) other).value == value;
+    }
+
+    @Override public int hashCode() {
+      return 37 * System.identityHashCode(value);
+    }
+
+    @Override public String toString() {
+      return "identicalTo(" + value + ")";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Returns a matcher which matches classes in the given package. Packages are specific to their
+   * classloader, so classes with the same package name may not have the same package at runtime.
+   */
+  public static Matcher<Class> inPackage(final Package targetPackage) {
+    return new InPackage(targetPackage);
+  }
+
+  private static class InPackage extends AbstractMatcher<Class> implements Serializable {
+    private final transient Package targetPackage;
+    private final String packageName;
+
+    public InPackage(Package targetPackage) {
+      this.targetPackage = checkNotNull(targetPackage, "package");
+      this.packageName = targetPackage.getName();
+    }
+
+    public boolean matches(Class c) {
+      return c.getPackage().equals(targetPackage);
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof InPackage
+          && ((InPackage) other).targetPackage.equals(targetPackage);
+    }
+
+    @Override public int hashCode() {
+      return 37 * targetPackage.hashCode();
+    }
+
+    @Override public String toString() {
+      return "inPackage(" + targetPackage.getName() + ")";
+    }
+
+    public Object readResolve() {
+      return inPackage(Package.getPackage(packageName));
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Returns a matcher which matches classes in the given package and its subpackages. Unlike
+   * {@link #inPackage(Package) inPackage()}, this matches classes from any classloader.
+   * 
+   * @since 2.0
+   */
+  public static Matcher<Class> inSubpackage(final String targetPackageName) {
+    return new InSubpackage(targetPackageName);
+  }
+
+  private static class InSubpackage extends AbstractMatcher<Class> implements Serializable {
+    private final String targetPackageName;
+
+    public InSubpackage(String targetPackageName) {
+      this.targetPackageName = targetPackageName;
+    }
+
+    public boolean matches(Class c) {
+      String classPackageName = c.getPackage().getName();
+      return classPackageName.equals(targetPackageName)
+          || classPackageName.startsWith(targetPackageName + ".");
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof InSubpackage
+          && ((InSubpackage) other).targetPackageName.equals(targetPackageName);
+    }
+
+    @Override public int hashCode() {
+      return 37 * targetPackageName.hashCode();
+    }
+
+    @Override public String toString() {
+      return "inSubpackage(" + targetPackageName + ")";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Returns a matcher which matches methods with matching return types.
+   */
+  public static Matcher<Method> returns(
+      final Matcher<? super Class<?>> returnType) {
+    return new Returns(returnType);
+  }
+
+  private static class Returns extends AbstractMatcher<Method> implements Serializable {
+    private final Matcher<? super Class<?>> returnType;
+
+    public Returns(Matcher<? super Class<?>> returnType) {
+      this.returnType = checkNotNull(returnType, "return type matcher");
+    }
+
+    public boolean matches(Method m) {
+      return returnType.matches(m.getReturnType());
+    }
+
+    @Override public boolean equals(Object other) {
+      return other instanceof Returns
+          && ((Returns) other).returnType.equals(returnType);
+    }
+
+    @Override public int hashCode() {
+      return 37 * returnType.hashCode();
+    }
+
+    @Override public String toString() {
+      return "returns(" + returnType + ")";
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+}
diff --git a/core/src/com/google/inject/matcher/package-info.java b/core/src/com/google/inject/matcher/package-info.java
new file mode 100644
index 0000000..ced3238
--- /dev/null
+++ b/core/src/com/google/inject/matcher/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Used for matching things. Primarily used to pick out methods to which to
+ * apply interceptors.
+ */
+package com.google.inject.matcher;
\ No newline at end of file
diff --git a/core/src/com/google/inject/name/Named.java b/core/src/com/google/inject/name/Named.java
new file mode 100644
index 0000000..23b3d5d
--- /dev/null
+++ b/core/src/com/google/inject/name/Named.java
@@ -0,0 +1,37 @@
+/**
+ * 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 com.google.inject.name;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates named things.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@BindingAnnotation
+public @interface Named {
+  String value();
+}
diff --git a/core/src/com/google/inject/name/NamedImpl.java b/core/src/com/google/inject/name/NamedImpl.java
new file mode 100644
index 0000000..2fe0107
--- /dev/null
+++ b/core/src/com/google/inject/name/NamedImpl.java
@@ -0,0 +1,59 @@
+/**
+ * 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 com.google.inject.name;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+
+class NamedImpl implements Named, Serializable {
+
+  private final String value;
+
+  public NamedImpl(String value) {
+    this.value = checkNotNull(value, "name");
+  }
+
+  public String value() {
+    return this.value;
+  }
+
+  public int hashCode() {
+    // This is specified in java.lang.Annotation.
+    return (127 * "value".hashCode()) ^ value.hashCode();
+  }
+
+  public boolean equals(Object o) {
+    if (!(o instanceof Named)) {
+      return false;
+    }
+
+    Named other = (Named) o;
+    return value.equals(other.value());
+  }
+
+  public String toString() {
+    return "@" + Named.class.getName() + "(value=" + value + ")";
+  }
+
+  public Class<? extends Annotation> annotationType() {
+    return Named.class;
+  }
+
+  private static final long serialVersionUID = 0;
+}
diff --git a/core/src/com/google/inject/name/Names.java b/core/src/com/google/inject/name/Names.java
new file mode 100644
index 0000000..f7ec971
--- /dev/null
+++ b/core/src/com/google/inject/name/Names.java
@@ -0,0 +1,70 @@
+/**
+ * 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 com.google.inject.name;
+
+import com.google.inject.Binder;
+import com.google.inject.Key;
+
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Utility methods for use with {@code @}{@link Named}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class Names {
+
+  private Names() {}
+
+  /**
+   * Creates a {@link Named} annotation with {@code name} as the value.
+   */
+  public static Named named(String name) {
+    return new NamedImpl(name);
+  }
+
+  /**
+   * Creates a constant binding to {@code @Named(key)} for each entry in
+   * {@code properties}.
+   */
+  public static void bindProperties(Binder binder, Map<String, String> properties) {
+    binder = binder.skipSources(Names.class);
+    for (Map.Entry<String, String> entry : properties.entrySet()) {
+      String key = entry.getKey();
+      String value = entry.getValue();
+      binder.bind(Key.get(String.class, new NamedImpl(key))).toInstance(value);
+    }
+  }
+
+  /**
+   * Creates a constant binding to {@code @Named(key)} for each property. This
+   * method binds all properties including those inherited from 
+   * {@link Properties#defaults defaults}.
+   */
+  public static void bindProperties(Binder binder, Properties properties) {
+    binder = binder.skipSources(Names.class);
+
+    // use enumeration to include the default properties
+    for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements(); ) {
+      String propertyName = (String) e.nextElement();
+      String value = properties.getProperty(propertyName);
+      binder.bind(Key.get(String.class, new NamedImpl(propertyName))).toInstance(value);
+    }
+  }
+}
diff --git a/core/src/com/google/inject/name/package-info.java b/core/src/com/google/inject/name/package-info.java
new file mode 100644
index 0000000..d6bf05d
--- /dev/null
+++ b/core/src/com/google/inject/name/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Support for binding to string-based names.
+ */
+package com.google.inject.name;
\ No newline at end of file
diff --git a/core/src/com/google/inject/package-info.java b/core/src/com/google/inject/package-info.java
new file mode 100644
index 0000000..626bde2
--- /dev/null
+++ b/core/src/com/google/inject/package-info.java
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+/**
+ * <i>Google Guice</i> (pronounced "juice") is an ultra-lightweight dependency
+ * injection framework.  Please refer to the Guice
+ * <a href="http://docs.google.com/Doc?id=dd2fhx4z_5df5hw8">User's Guide</a>
+ * for a gentle introduction.
+ *
+ * <p>The principal public APIs in this package are:
+ *
+ * <dl>
+ * <dt>{@link com.google.inject.Inject}
+ * <dd>The annotation you will use in your implementation classes to tell Guice
+ *     where and how it should send in ("inject") the objects you depend on
+ *     (your "dependencies").
+ *
+ * <dt>{@link com.google.inject.Module}
+ * <dd>The interface you will implement in order to specify "bindings" --
+ *     instructions for how Guice should handle injection -- for a particular
+ *     set of interfaces.
+ *
+ * <dt>{@link com.google.inject.Binder}
+ * <dd>The object that Guice passes into your {@link com.google.inject.Module}
+ *     to collect these bindings.
+ *
+ * <dt>{@link com.google.inject.Provider}
+ * <dd>The interface you will implement when you need to customize exactly how
+ *     Guice creates instances for a particular binding.
+ *
+ * </dl>
+ *
+ */
+package com.google.inject;
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/BindingScopingVisitor.java b/core/src/com/google/inject/spi/BindingScopingVisitor.java
new file mode 100644
index 0000000..2abfc9e
--- /dev/null
+++ b/core/src/com/google/inject/spi/BindingScopingVisitor.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Scope;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Visits each of the strategies used to scope an injection.
+ *
+ * @param <V> any type to be returned by the visit method. Use {@link Void} with
+ *     {@code return null} if no return type is needed.
+ * @since 2.0
+ */
+public interface BindingScopingVisitor<V> {
+
+  /**
+   * Visit an eager singleton or single instance. This scope strategy is found on both module and
+   * injector bindings.
+   */
+  V visitEagerSingleton();
+
+  /**
+   * Visit a scope instance. This scope strategy is found on both module and injector bindings.
+   */
+  V visitScope(Scope scope);
+
+  /**
+   * Visit a scope annotation. This scope strategy is found only on module bindings. The instance
+   * that implements this scope is registered by {@link com.google.inject.Binder#bindScope(Class,
+   * Scope) Binder.bindScope()}.
+   */
+  V visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation);
+
+  /**
+   * Visit an unspecified or unscoped strategy. On a module, this strategy indicates that the
+   * injector should use scoping annotations to find a scope. On an injector, it indicates that
+   * no scope is applied to the binding. An unscoped binding will behave like a scoped one when it
+   * is linked to a scoped binding.
+   */
+  V visitNoScoping();
+}
diff --git a/core/src/com/google/inject/spi/BindingTargetVisitor.java b/core/src/com/google/inject/spi/BindingTargetVisitor.java
new file mode 100644
index 0000000..7137d74
--- /dev/null
+++ b/core/src/com/google/inject/spi/BindingTargetVisitor.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+/**
+ * Visits each of the strategies used to find an instance to satisfy an injection.
+ *
+ * @param <V> any type to be returned by the visit method. Use {@link Void} with
+ *     {@code return null} if no return type is needed.
+ * @since 2.0
+ */
+public interface BindingTargetVisitor<T, V> {
+
+  /**
+   * Visit a instance binding. The same instance is returned for every injection. This target is
+   * found in both module and injector bindings.
+   */
+  V visit(InstanceBinding<? extends T> binding);
+
+  /**
+   * Visit a provider instance binding. The provider's {@code get} method is invoked to resolve
+   * injections. This target is found in both module and injector bindings.
+   */
+  V visit(ProviderInstanceBinding<? extends T> binding);
+
+  /**
+   * Visit a provider key binding. To resolve injections, the provider key is first resolved, then
+   * that provider's {@code get} method is invoked. This target is found in both module and injector
+   * bindings.
+   */
+  V visit(ProviderKeyBinding<? extends T> binding);
+
+  /**
+   * Visit a linked key binding. The other key's binding is used to resolve injections. This
+   * target is found in both module and injector bindings.
+   */
+  V visit(LinkedKeyBinding<? extends T> binding);
+
+  /**
+   * Visit a binding to a key exposed from an enclosed private environment. This target is only
+   * found in injector bindings.
+   */
+  V visit(ExposedBinding<? extends T> binding);
+
+  /**
+   * Visit an untargetted binding. This target is found only on module bindings. It indicates
+   * that the injector should use its implicit binding strategies to resolve injections.
+   */
+  V visit(UntargettedBinding<? extends T> binding);
+
+  /**
+   * Visit a constructor binding. To resolve injections, an instance is instantiated by invoking
+   * {@code constructor}. This target is found only on injector bindings.
+   */
+  V visit(ConstructorBinding<? extends T> binding);
+
+  /**
+   * Visit a binding created from converting a bound instance to a new type. The source binding
+   * has the same binding annotation but a different type. This target is found only on injector
+   * bindings.
+   */
+  V visit(ConvertedConstantBinding<? extends T> binding);
+
+  /**
+   * Visit a binding to a {@link com.google.inject.Provider} that delegates to the binding for the
+   * provided type. This target is found only on injector bindings.
+   */
+  V visit(ProviderBinding<? extends T> binding);
+}
diff --git a/core/src/com/google/inject/spi/ConstructorBinding.java b/core/src/com/google/inject/spi/ConstructorBinding.java
new file mode 100644
index 0000000..6799941
--- /dev/null
+++ b/core/src/com/google/inject/spi/ConstructorBinding.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A binding to the constructor of a concrete clss. To resolve injections, an instance is
+ * instantiated by invoking the constructor.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface ConstructorBinding<T> extends Binding<T>, HasDependencies {
+
+  /**
+   * Gets the constructor this binding injects.
+   */
+  InjectionPoint getConstructor();
+
+  /**
+   * Returns all instance method and field injection points on {@code type}.
+   *
+   * @return a possibly empty set of injection points. The set has a specified iteration order. All
+   *      fields are returned and then all methods. Within the fields, supertype fields are returned
+   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+   */
+  Set<InjectionPoint> getInjectableMembers();
+
+  /*if[AOP]*/
+  /**
+   * Returns the interceptors applied to each method, in the order that they will be applied.
+   *
+   * @return a possibly empty map
+   */
+  Map<Method, List<org.aopalliance.intercept.MethodInterceptor>> getMethodInterceptors();
+  /*end[AOP]*/
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/ConvertedConstantBinding.java b/core/src/com/google/inject/spi/ConvertedConstantBinding.java
new file mode 100644
index 0000000..5582fb6
--- /dev/null
+++ b/core/src/com/google/inject/spi/ConvertedConstantBinding.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Key;
+
+import java.util.Set;
+
+/**
+ * A binding created from converting a bound instance to a new type. The source binding has the same
+ * binding annotation but a different type.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface ConvertedConstantBinding<T> extends Binding<T>, HasDependencies {
+
+  /**
+   * Returns the converted value.
+   */
+  T getValue();
+
+  /**
+   * Returns the type converter binding used to convert the constant.
+   * 
+   * @since 3.0
+   */
+  TypeConverterBinding getTypeConverterBinding();
+
+  /**
+   * Returns the key for the source binding. That binding can be retrieved from an injector using
+   * {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.
+   */
+  Key<String> getSourceKey();
+
+  /**
+   * Returns a singleton set containing only the converted key.
+   */
+  Set<Dependency<?>> getDependencies();
+}
diff --git a/core/src/com/google/inject/spi/DefaultBindingScopingVisitor.java b/core/src/com/google/inject/spi/DefaultBindingScopingVisitor.java
new file mode 100644
index 0000000..b517272
--- /dev/null
+++ b/core/src/com/google/inject/spi/DefaultBindingScopingVisitor.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Scope;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * No-op visitor for subclassing. All interface methods simply delegate to
+ * {@link #visitOther()}, returning its result.
+ *
+ * @param <V> any type to be returned by the visit method. Use {@link Void} with
+ *     {@code return null} if no return type is needed.
+ * 
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public class DefaultBindingScopingVisitor<V> implements BindingScopingVisitor<V> {
+
+  /**
+   * Default visit implementation. Returns {@code null}.
+   */
+  protected V visitOther() {
+    return null;
+  }
+
+  public V visitEagerSingleton() {
+    return visitOther();
+  }
+
+  public V visitScope(Scope scope) {
+    return visitOther();
+  }
+
+  public V visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
+    return visitOther();
+  }
+
+  public V visitNoScoping() {
+    return visitOther();
+  }
+}
diff --git a/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java b/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java
new file mode 100644
index 0000000..3deb9dd
--- /dev/null
+++ b/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+
+/**
+ * No-op visitor for subclassing. All interface methods simply delegate to {@link
+ * #visitOther(Binding)}, returning its result.
+ *
+ * @param <V> any type to be returned by the visit method. Use {@link Void} with
+ *     {@code return null} if no return type is needed.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public abstract class DefaultBindingTargetVisitor<T, V> implements BindingTargetVisitor<T, V> {
+
+  /**
+   * Default visit implementation. Returns {@code null}.
+   */
+  protected V visitOther(Binding<? extends T> binding) {
+    return null;
+  }
+
+  public V visit(InstanceBinding<? extends T> instanceBinding) {
+    return visitOther(instanceBinding);
+  }
+
+  public V visit(ProviderInstanceBinding<? extends T> providerInstanceBinding) {
+    return visitOther(providerInstanceBinding);
+  }
+
+  public V visit(ProviderKeyBinding<? extends T> providerKeyBinding) {
+    return visitOther(providerKeyBinding);
+  }
+
+  public V visit(LinkedKeyBinding<? extends T> linkedKeyBinding) {
+    return visitOther(linkedKeyBinding);
+  }
+
+  public V visit(ExposedBinding<? extends T> exposedBinding) {
+    return visitOther(exposedBinding);
+  }
+
+  public V visit(UntargettedBinding<? extends T> untargettedBinding) {
+    return visitOther(untargettedBinding);
+  }
+
+  public V visit(ConstructorBinding<? extends T> constructorBinding) {
+    return visitOther(constructorBinding);
+  }
+
+  public V visit(ConvertedConstantBinding<? extends T> convertedConstantBinding) {
+    return visitOther(convertedConstantBinding);
+  }
+
+  @SuppressWarnings("unchecked")
+  public V visit(ProviderBinding<? extends T> providerBinding) {
+    // TODO(cushon): remove raw (Binding) cast when we don't care about javac 6 anymore
+    return visitOther((Binding<? extends T>) (Binding) providerBinding);
+  }
+}
diff --git a/core/src/com/google/inject/spi/DefaultElementVisitor.java b/core/src/com/google/inject/spi/DefaultElementVisitor.java
new file mode 100644
index 0000000..1bbea0d
--- /dev/null
+++ b/core/src/com/google/inject/spi/DefaultElementVisitor.java
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+
+/**
+ * No-op visitor for subclassing. All interface methods simply delegate to
+ * {@link #visitOther(Element)}, returning its result.
+ *
+ * @param <V> any type to be returned by the visit method. Use {@link Void} with
+ *     {@code return null} if no return type is needed.
+ *
+ * @author sberlin@gmail.com (Sam Berlin)
+ * @since 2.0
+ */
+public abstract class DefaultElementVisitor<V> implements ElementVisitor<V> {
+
+  /**
+   * Default visit implementation. Returns {@code null}.
+   */
+  protected V visitOther(Element element) {
+    return null;
+  }
+
+  public V visit(Message message) {
+    return visitOther(message);
+  }
+
+  public <T> V visit(Binding<T> binding) {
+    return visitOther(binding);
+  }
+
+  /*if[AOP]*/
+  public V visit(InterceptorBinding interceptorBinding) {
+    return visitOther(interceptorBinding);
+  }
+  /*end[AOP]*/
+
+  public V visit(ScopeBinding scopeBinding) {
+    return visitOther(scopeBinding);
+  }
+
+  public V visit(TypeConverterBinding typeConverterBinding) {
+    return visitOther(typeConverterBinding);
+  }
+
+  public <T> V visit(ProviderLookup<T> providerLookup) {
+    return visitOther(providerLookup);
+  }
+
+  public V visit(InjectionRequest<?> injectionRequest) {
+    return visitOther(injectionRequest);
+  }
+
+  public V visit(StaticInjectionRequest staticInjectionRequest) {
+    return visitOther(staticInjectionRequest);
+  }
+
+  public V visit(PrivateElements privateElements) {
+    return visitOther(privateElements);
+  }
+
+  public <T> V visit(MembersInjectorLookup<T> lookup) {
+    return visitOther(lookup);
+  }
+
+  public V visit(TypeListenerBinding binding) {
+    return visitOther(binding);
+  }
+  
+  public V visit(ProvisionListenerBinding binding) {
+    return visitOther(binding);
+  }
+  
+  public V visit(DisableCircularProxiesOption option) {
+    return visitOther(option);
+  }
+  
+  public V visit(RequireExplicitBindingsOption option) {
+    return visitOther(option);
+  }
+  
+  public V visit(RequireAtInjectOnConstructorsOption option) {
+    return visitOther(option);
+  }
+
+  public V visit(RequireExactBindingAnnotationsOption option) {
+    return visitOther(option);
+  }
+
+  public V visit(ModuleAnnotatedMethodScannerBinding binding) {
+    return visitOther(binding);
+  }
+}
diff --git a/core/src/com/google/inject/spi/Dependency.java b/core/src/com/google/inject/spi/Dependency.java
new file mode 100644
index 0000000..f86e255
--- /dev/null
+++ b/core/src/com/google/inject/spi/Dependency.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.Key;
+import com.google.inject.internal.MoreTypes;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A variable that can be resolved by an injector.
+ *
+ * <p>Use {@link #get} to build a freestanding dependency, or {@link InjectionPoint} to build one
+ * that's attached to a constructor, method or field.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class Dependency<T> {
+  private final InjectionPoint injectionPoint;
+  private final Key<T> key;
+  private final boolean nullable;
+  private final int parameterIndex;
+
+  Dependency(InjectionPoint injectionPoint, Key<T> key, boolean nullable, int parameterIndex) {
+    this.injectionPoint = injectionPoint;
+    this.key = checkNotNull(key, "key");
+    this.nullable = nullable;
+    this.parameterIndex = parameterIndex;
+  }
+
+  /**
+   * Returns a new dependency that is not attached to an injection point. The returned dependency is
+   * nullable.
+   */
+  public static <T> Dependency<T> get(Key<T> key) {
+    return new Dependency<T>(null, MoreTypes.canonicalizeKey(key), true, -1);
+  }
+
+  /**
+   * Returns the dependencies from the given injection points.
+   */
+  public static Set<Dependency<?>> forInjectionPoints(Set<InjectionPoint> injectionPoints) {
+    List<Dependency<?>> dependencies = Lists.newArrayList();
+    for (InjectionPoint injectionPoint : injectionPoints) {
+      dependencies.addAll(injectionPoint.getDependencies());
+    }
+    return ImmutableSet.copyOf(dependencies);
+  }
+
+  /**
+   * Returns the key to the binding that satisfies this dependency.
+   */
+  public Key<T> getKey() {
+    return this.key;
+  }
+
+  /**
+   * Returns true if null is a legal value for this dependency.
+   */
+  public boolean isNullable() {
+    return nullable;
+  }
+
+  /**
+   * Returns the injection point to which this dependency belongs, or null if this dependency isn't
+   * attached to a particular injection point.
+   */
+  public InjectionPoint getInjectionPoint() {
+    return injectionPoint;
+  }
+
+  /**
+   * Returns the index of this dependency in the injection point's parameter list, or {@code -1} if
+   * this dependency does not belong to a parameter list. Only method and constuctor dependencies
+   * are elements in a parameter list.
+   */
+  public int getParameterIndex() {
+    return parameterIndex;
+  }
+
+  @Override public int hashCode() {
+    return Objects.hashCode(injectionPoint, parameterIndex, key);
+  }
+
+  @Override public boolean equals(Object o) {
+    if (o instanceof Dependency) {
+      Dependency dependency = (Dependency) o;
+      return Objects.equal(injectionPoint, dependency.injectionPoint)
+          && Objects.equal(parameterIndex, dependency.parameterIndex)
+          && Objects.equal(key, dependency.key);
+    } else {
+      return false;
+    }
+  }
+
+  @Override public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append(key);
+    if (injectionPoint != null) {
+      builder.append("@").append(injectionPoint);
+      if (parameterIndex != -1) {
+        builder.append("[").append(parameterIndex).append("]");
+      }
+    }
+    return builder.toString();
+  }
+}
diff --git a/core/src/com/google/inject/spi/DependencyAndSource.java b/core/src/com/google/inject/spi/DependencyAndSource.java
new file mode 100644
index 0000000..ce52aae
--- /dev/null
+++ b/core/src/com/google/inject/spi/DependencyAndSource.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.inject.spi;
+
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.internal.util.StackTraceElements;
+
+import java.lang.reflect.Member;
+
+/**
+ * A combination of a {@link Dependency} and the {@link Binding#getSource()
+ * source} where the dependency was bound.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+public final class DependencyAndSource {
+  private final Dependency<?> dependency;
+  private final Object source;
+
+  public DependencyAndSource(Dependency<?> dependency, Object source) {
+    this.dependency = dependency;
+    this.source = source;
+  }
+
+  /**
+   * Returns the Dependency, if one exists. For anything that can be referenced
+   * by {@link Injector#getBinding}, a dependency exists. A dependency will not
+   * exist (and this will return null) for types initialized with
+   * {@link Binder#requestInjection} or {@link Injector#injectMembers(Object)},
+   * nor will it exist for objects injected into Providers bound with
+   * LinkedBindingBuilder#toProvider(Provider).
+   */
+  public Dependency<?> getDependency() {
+    return dependency;
+  }
+
+  /**
+   * Returns a string describing where this dependency was bound. If the binding
+   * was just-in-time, there is no valid binding source, so this describes the
+   * class in question.
+   */
+  public String getBindingSource() {
+    if (source instanceof Class) {
+      return StackTraceElements.forType((Class) source).toString();
+    } else if (source instanceof Member) {
+      return StackTraceElements.forMember((Member) source).toString();
+    } else {
+      return source.toString();
+    }
+  }
+
+  @Override
+  public String toString() {
+    Dependency<?> dep = getDependency();
+    Object source = getBindingSource();
+    if (dep != null) {
+      return "Dependency: " + dep + ", source: " + source;
+    } else {
+      return "Source: " + source;
+    }
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/DisableCircularProxiesOption.java b/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
new file mode 100644
index 0000000..4193e0a
--- /dev/null
+++ b/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2010 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+
+/**
+ * A request to disable circular proxies.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 3.0
+ */
+public final class DisableCircularProxiesOption implements Element {
+  private final Object source;
+
+  DisableCircularProxiesOption(Object source) {
+    this.source = checkNotNull(source, "source");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).disableCircularProxies();
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+}
diff --git a/core/src/com/google/inject/spi/Element.java b/core/src/com/google/inject/spi/Element.java
new file mode 100644
index 0000000..814ccef
--- /dev/null
+++ b/core/src/com/google/inject/spi/Element.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binder;
+
+/**
+ * A core component of a module or injector.
+ *
+ * <p>The elements of a module can be inspected, validated and rewritten. Use {@link
+ * Elements#getElements(com.google.inject.Module[]) Elements.getElements()} to read the elements
+ * from a module, and {@link Elements#getModule(Iterable) Elements.getModule()} to rewrite them.
+ * This can be used for static analysis and generation of Guice modules.
+ *
+ * <p>The elements of an injector can be inspected and exercised. Use {@link
+ * com.google.inject.Injector#getBindings Injector.getBindings()} to reflect on Guice injectors.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @author crazybob@google.com (Bob Lee)
+ * @since 2.0
+ */
+public interface Element {
+
+  /**
+   * Returns an arbitrary object containing information about the "place" where this element was
+   * configured. Used by Guice in the production of descriptive error messages.
+   *
+   * <p>Tools might specially handle types they know about; {@code StackTraceElement} is a good
+   * example. Tools should simply call {@code toString()} on the source object if the type is
+   * unfamiliar.
+   */
+  Object getSource();
+
+  /**
+   * Accepts an element visitor. Invokes the visitor method specific to this element's type.
+   *
+   * @param visitor to call back on
+   */
+  <T> T acceptVisitor(ElementVisitor<T> visitor);
+
+  /**
+   * Writes this module element to the given binder (optional operation).
+   *
+   * @param binder to apply configuration element to
+   * @throws UnsupportedOperationException if the {@code applyTo} method is not supported by this
+   *     element.
+   */
+  void applyTo(Binder binder);
+
+}
diff --git a/core/src/com/google/inject/spi/ElementSource.java b/core/src/com/google/inject/spi/ElementSource.java
new file mode 100644
index 0000000..52783c9
--- /dev/null
+++ b/core/src/com/google/inject/spi/ElementSource.java
@@ -0,0 +1,192 @@
+/**
+ * Copyright (C) 2013 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.inject.spi;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.internal.util.StackTraceElements.InMemoryStackTraceElement;
+
+import java.util.List;
+
+/**
+ * Contains information about where and how an {@link Element element} was
+ * bound.
+ * <p>
+ * The {@link #getDeclaringSource() declaring source} refers to a location in
+ * source code that defines the Guice {@link Element element}. For example, if
+ * the element is created from a method annotated by {@literal @Provides}, the
+ * declaring source of element would be the method itself.
+ * <p>
+ * The {@link #getStackTrace()} refers to the sequence of calls ends at one of
+ * {@link com.google.inject.Binder} {@code bindXXX()} methods and eventually
+ * defines the element. Note that {@link #getStackTrace()} lists
+ * {@link StackTraceElement StackTraceElements} in reverse chronological order.
+ * The first element (index zero) is the last method call and the last element
+ * is the first method invocation. By default, the stack trace is not collected.
+ * The default behavior can be changed by setting the
+ * {@code guice_include_stack_traces} flag value. The value can be either
+ * {@code OFF}, {@code ONLY_FOR_DECLARING_SOURCE} or {@code COMPLETE}. Note that
+ * collecting stack traces for every binding can cause a performance hit when
+ * the injector is created.
+ * <p>
+ * The sequence of class names of {@link com.google.inject.Module modules}
+ * involved in the element creation can be retrieved by
+ * {@link #getModuleClassNames()}. Similar to {@link #getStackTrace()}, the
+ * order is reverse chronological. The first module (index 0) is the module that
+ * installs the {@link Element element}. The last module is the root module.
+ * <p>
+ * In order to support the cases where a Guice {@link Element element} is
+ * created from another Guice {@link Element element} (original) (e.g., by
+ * {@link Element#applyTo}), it also provides a reference to the original
+ * element source ({@link #getOriginalElementSource()}).
+ *
+ * @since 4.0
+ */
+public final class ElementSource {
+
+  /** 
+   * The {@link ElementSource source} of element that this element created from (if there is any),
+   * otherwise {@code null}.
+   */
+  final ElementSource originalElementSource;
+  
+  /** The {@link ModuleSource source} of module creates the element. */
+  final ModuleSource moduleSource;
+  
+  /** 
+   * The partial call stack that starts at the last module {@link Module#Configure(Binder)
+   * configure(Binder)} call. The value is empty if stack trace collection is off.
+   */
+  final InMemoryStackTraceElement[] partialCallStack;
+  
+  /** 
+   * Refers to a single location in source code that causes the element creation. It can be any 
+   * object such as {@link Constructor}, {@link Method}, {@link Field}, {@link StackTraceElement}, 
+   * etc. For example, if the element is created from a method annotated by {@literal @Provides}, 
+   * the declaring source of element would be the method itself.
+   */
+  final Object declaringSource;
+
+  /**
+   * Creates a new {@ElementSource} from the given parameters. 
+   * @param originalElementSource The source of element that this element created from (if there is
+   * any), otherwise {@code null}.
+   * @param declaringSource the source (in)directly declared the element.
+   * @param moduleSource the moduleSource when the element is bound
+   * @param partialCallStack the partial call stack from the top module to where the element is 
+   * bound
+   */
+  ElementSource(/* @Nullable */ ElementSource originalSource, Object declaringSource, 
+      ModuleSource moduleSource, StackTraceElement[] partialCallStack) {
+    Preconditions.checkNotNull(declaringSource, "declaringSource cannot be null.");
+    Preconditions.checkNotNull(moduleSource, "moduleSource cannot be null.");
+    Preconditions.checkNotNull(partialCallStack, "partialCallStack cannot be null.");
+    this.originalElementSource = originalSource;
+    this.declaringSource = declaringSource;
+    this.moduleSource = moduleSource;
+    this.partialCallStack = StackTraceElements.convertToInMemoryStackTraceElement(partialCallStack);
+  }
+  
+  /**
+   * Returns the {@link ElementSource} of the element this was created or copied from. If this was
+   * not created or copied from another element, returns {@code null}.
+   */
+  public ElementSource getOriginalElementSource() {
+    return originalElementSource;
+  }
+  
+  /**
+   * Returns a single location in source code that defines the element. It can be any object
+   * such as {@link java.lang.reflect.Constructor}, {@link java.lang.reflect.Method},
+   * {@link java.lang.reflect.Field}, {@link StackTraceElement}, etc. For
+   * example, if the element is created from a method annotated by {@literal @Provides}, the
+   * declaring source of element would be the method itself.
+   */
+  public Object getDeclaringSource() {
+    return declaringSource;
+  }
+  
+  /**
+   * Returns the class names of modules involved in creating this {@link Element}. The first
+   * element (index 0) is the class name of module that defined the element, and the last element
+   * is the class name of root module.
+   */
+  public List<String> getModuleClassNames() {
+    return moduleSource.getModuleClassNames();
+  }
+
+  /**
+   * Returns the position of {@link com.google.inject.Module#configure configure(Binder)} method
+   * call in the {@link #getStackTrace stack trace} for modules that their classes returned by
+   * {@link #getModuleClassNames}. For example, if the stack trace looks like the following:
+   * <p>
+   * {@code
+   *  0 - Binder.bind(),
+   *  1 - ModuleTwo.configure(),
+   *  2 - Binder.install(),
+   *  3 - ModuleOne.configure(),
+   *  4 - theRest(). 
+   * }
+   * <p>
+   * 1 and 3 are returned.
+   * <p>
+   * In the cases where stack trace is not available (i.e., the stack trace was not collected),
+   * it returns -1 for all module positions.
+   */
+  public List<Integer> getModuleConfigurePositionsInStackTrace() {
+    int size = moduleSource.size();
+    Integer[] positions = new Integer[size];
+    int chunkSize = partialCallStack.length;
+    positions[0] = chunkSize - 1;
+    ModuleSource current = moduleSource;
+    for (int cursor = 1; cursor < size; cursor++) {
+      chunkSize = current.getPartialCallStackSize();
+      positions[cursor] = positions[cursor - 1] + chunkSize;
+      current = current.getParent();
+    }
+    return ImmutableList.<Integer>copyOf(positions);
+  }
+
+  /**
+   * Returns the sequence of method calls that ends at one of {@link com.google.inject.Binder}
+   * {@code bindXXX()} methods and eventually defines the element. Note that
+   * {@link #getStackTrace} lists {@link StackTraceElement StackTraceElements} in reverse
+   * chronological order. The first element (index zero) is the last method call and the last
+   * element is the first method invocation. In the cases where stack trace is not available
+   * (i.e.,the stack trace was not collected), it returns an empty array.
+   */
+  public StackTraceElement[] getStackTrace() {
+    int modulesCallStackSize = moduleSource.getStackTraceSize();
+    int chunkSize = partialCallStack.length;
+    int size = moduleSource.getStackTraceSize() + chunkSize;
+    StackTraceElement[] callStack = new StackTraceElement[size];
+    System.arraycopy(
+        StackTraceElements.convertToStackTraceElement(partialCallStack), 0, callStack, 0, 
+        chunkSize);
+    System.arraycopy(moduleSource.getStackTrace(), 0, callStack, chunkSize, modulesCallStackSize);
+    return callStack;
+  }
+
+  /**
+   * Returns {@code getDeclaringSource().toString()} value.
+   */
+  @Override
+  public String toString() {
+    return getDeclaringSource().toString();
+  }
+}
diff --git a/core/src/com/google/inject/spi/ElementVisitor.java b/core/src/com/google/inject/spi/ElementVisitor.java
new file mode 100644
index 0000000..bc0d910
--- /dev/null
+++ b/core/src/com/google/inject/spi/ElementVisitor.java
@@ -0,0 +1,133 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Inject;
+
+/**
+ * Visit elements.
+ *
+ * @param <V> any type to be returned by the visit method. Use {@link Void} with
+ *     {@code return null} if no return type is needed.
+ * 
+ * @since 2.0
+ */
+public interface ElementVisitor<V> {
+
+  /**
+   * Visit a mapping from a key (type and optional annotation) to the strategy for getting
+   * instances of the type.
+   */
+  <T> V visit(Binding<T> binding);
+
+  /*if[AOP]*/
+  /**
+   * Visit a registration of interceptors for matching methods of matching classes.
+   */
+  V visit(InterceptorBinding binding);
+  /*end[AOP]*/
+
+  /**
+   * Visit a registration of a scope annotation with the scope that implements it.
+   */
+  V visit(ScopeBinding binding);
+
+  /**
+   * Visit a registration of type converters for matching target types.
+   */
+  V visit(TypeConverterBinding binding);
+
+  /**
+   * Visit a request to inject the instance fields and methods of an instance.
+   */
+  V visit(InjectionRequest<?> request);
+
+  /**
+   * Visit a request to inject the static fields and methods of type.
+   */
+  V visit(StaticInjectionRequest request);
+
+  /**
+   * Visit a lookup of the provider for a type.
+   */
+  <T> V visit(ProviderLookup<T> lookup);
+
+  /**
+   * Visit a lookup of the members injector.
+   */
+  <T> V visit(MembersInjectorLookup<T> lookup);
+
+  /**
+   * Visit an error message and the context in which it occured.
+   */
+  V visit(Message message);
+
+  /**
+   * Visit a collection of configuration elements for a {@linkplain com.google.inject.PrivateBinder
+   * private binder}.
+   */
+  V visit(PrivateElements elements);
+
+  /**
+   * Visit an injectable type listener binding.
+   */
+  V visit(TypeListenerBinding binding);
+  
+  /**
+   * Visit a provision listener binding.
+   *
+   * @since 4.0
+   */
+  V visit(ProvisionListenerBinding binding);
+  
+  /**
+   * Visit a require explicit bindings command.
+   * 
+   * @since 3.0
+   */
+  V visit(RequireExplicitBindingsOption option);
+  
+  /**
+   * Visit a disable circular proxies command.
+   * 
+   * @since 3.0
+   */
+  V visit(DisableCircularProxiesOption option);
+  
+  /**
+   * Visit a require explicit {@literal @}{@link Inject} command.
+   * 
+   * @since 4.0
+   */
+  V visit(RequireAtInjectOnConstructorsOption option);
+
+  /**
+   * Visit a require exact binding annotations command.
+   *
+   * @since 4.0
+   */
+  V visit(RequireExactBindingAnnotationsOption option);
+
+  /**
+   * Visits a {@link Binder#scanModulesForAnnotatedMethods} command.
+   *
+   * @since 4.0
+   */
+  V visit(ModuleAnnotatedMethodScannerBinding binding);
+}
diff --git a/core/src/com/google/inject/spi/Elements.java b/core/src/com/google/inject/spi/Elements.java
new file mode 100644
index 0000000..9348276
--- /dev/null
+++ b/core/src/com/google/inject/spi/Elements.java
@@ -0,0 +1,565 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.inject.internal.InternalFlags.getIncludeStackTraceOption;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Module;
+import com.google.inject.PrivateBinder;
+import com.google.inject.PrivateModule;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.AnnotatedConstantBindingBuilder;
+import com.google.inject.binder.AnnotatedElementBuilder;
+import com.google.inject.internal.AbstractBindingBuilder;
+import com.google.inject.internal.BindingBuilder;
+import com.google.inject.internal.ConstantBindingBuilderImpl;
+import com.google.inject.internal.Errors;
+import com.google.inject.internal.ExposureBuilder;
+import com.google.inject.internal.InternalFlags.IncludeStackTraceOption;
+import com.google.inject.internal.MoreTypes;
+import com.google.inject.internal.PrivateElementsImpl;
+import com.google.inject.internal.ProviderMethodsModule;
+import com.google.inject.internal.util.SourceProvider;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.matcher.Matcher;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Exposes elements of a module so they can be inspected, validated or {@link
+ * Element#applyTo(Binder) rewritten}.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class Elements {
+
+  private static final BindingTargetVisitor<Object, Object> GET_INSTANCE_VISITOR
+      = new DefaultBindingTargetVisitor<Object, Object>() {
+    @Override public Object visit(InstanceBinding<?> binding) {
+      return binding.getInstance();
+    }
+
+    @Override protected Object visitOther(Binding<?> binding) {
+      throw new IllegalArgumentException();
+    }
+  };
+
+  /**
+   * Records the elements executed by {@code modules}.
+   */
+  public static List<Element> getElements(Module... modules) {
+    return getElements(Stage.DEVELOPMENT, Arrays.asList(modules));
+  }
+
+  /**
+   * Records the elements executed by {@code modules}.
+   */
+  public static List<Element> getElements(Stage stage, Module... modules) {
+    return getElements(stage, Arrays.asList(modules));
+  }
+
+  /**
+   * Records the elements executed by {@code modules}.
+   */
+  public static List<Element> getElements(Iterable<? extends Module> modules) {
+    return getElements(Stage.DEVELOPMENT, modules);
+  }
+
+  /**
+   * Records the elements executed by {@code modules}.
+   */
+  public static List<Element> getElements(Stage stage, Iterable<? extends Module> modules) {
+    RecordingBinder binder = new RecordingBinder(stage);
+    for (Module module : modules) {
+      binder.install(module);
+    }
+    binder.scanForAnnotatedMethods();
+    for (RecordingBinder child : binder.privateBinders) {
+      child.scanForAnnotatedMethods();
+    }
+    // Free the memory consumed by the stack trace elements cache
+    StackTraceElements.clearCache();
+    return Collections.unmodifiableList(binder.elements);
+  }
+
+  private static class ElementsAsModule implements Module {
+    private final Iterable<? extends Element> elements;
+
+    ElementsAsModule(Iterable<? extends Element> elements) {
+      this.elements = elements;
+    }
+
+    @Override
+    public void configure(Binder binder) {
+      for (Element element : elements) {
+        element.applyTo(binder);
+      }
+    }
+  }
+
+  /**
+   * Returns the module composed of {@code elements}.
+   */
+  public static Module getModule(final Iterable<? extends Element> elements) {
+    return new ElementsAsModule(elements);
+  }
+
+  @SuppressWarnings("unchecked")
+  static <T> BindingTargetVisitor<T, T> getInstanceVisitor() {
+    return (BindingTargetVisitor<T, T>) GET_INSTANCE_VISITOR;
+  }
+
+  private static class ModuleInfo {
+    private final Binder binder;
+    private final ModuleSource moduleSource;
+    private final boolean skipScanning;
+
+    private ModuleInfo(Binder binder, ModuleSource moduleSource, boolean skipScanning) {
+      this.binder = binder;
+      this.moduleSource = moduleSource;
+      this.skipScanning = skipScanning;
+    }
+  }
+
+  private static class RecordingBinder implements Binder, PrivateBinder {
+    private final Stage stage;
+    private final Map<Module, ModuleInfo> modules;
+    private final List<Element> elements;
+    private final Object source;
+    /** The current modules stack */
+    private ModuleSource moduleSource = null;
+    private final SourceProvider sourceProvider;
+    private final Set<ModuleAnnotatedMethodScanner> scanners;
+
+    /** The binder where exposed bindings will be created */
+    private final RecordingBinder parent;
+    private final PrivateElementsImpl privateElements;
+
+    /** All children private binders, so we can scan through them. */
+    private final List<RecordingBinder> privateBinders;
+
+    private RecordingBinder(Stage stage) {
+      this.stage = stage;
+      this.modules = Maps.newLinkedHashMap();
+      this.scanners = Sets.newLinkedHashSet();
+      this.elements = Lists.newArrayList();
+      this.source = null;
+      this.sourceProvider = SourceProvider.DEFAULT_INSTANCE.plusSkippedClasses(
+          Elements.class, RecordingBinder.class, AbstractModule.class,
+          ConstantBindingBuilderImpl.class, AbstractBindingBuilder.class, BindingBuilder.class);
+      this.parent = null;
+      this.privateElements = null;
+      this.privateBinders = Lists.newArrayList();
+    }
+
+    /** Creates a recording binder that's backed by {@code prototype}. */
+    private RecordingBinder(
+        RecordingBinder prototype, Object source, SourceProvider sourceProvider) {
+      checkArgument(source == null ^ sourceProvider == null);
+
+      this.stage = prototype.stage;
+      this.modules = prototype.modules;
+      this.elements = prototype.elements;
+      this.scanners = prototype.scanners;
+      this.source = source;
+      this.moduleSource = prototype.moduleSource;
+      this.sourceProvider = sourceProvider;
+      this.parent = prototype.parent;
+      this.privateElements = prototype.privateElements;
+      this.privateBinders = prototype.privateBinders;
+    }
+
+    /** Creates a private recording binder. */
+    private RecordingBinder(RecordingBinder parent, PrivateElementsImpl privateElements) {
+      this.stage = parent.stage;
+      this.modules = Maps.newLinkedHashMap();
+      this.scanners = Sets.newLinkedHashSet(parent.scanners);
+      this.elements = privateElements.getElementsMutable();
+      this.source = parent.source;
+      this.moduleSource = parent.moduleSource;
+      this.sourceProvider = parent.sourceProvider;
+      this.parent = parent;
+      this.privateElements = privateElements;
+      this.privateBinders = parent.privateBinders;
+    }
+
+    /*if[AOP]*/
+    @Override
+    public void bindInterceptor(
+        Matcher<? super Class<?>> classMatcher,
+        Matcher<? super Method> methodMatcher,
+        org.aopalliance.intercept.MethodInterceptor... interceptors) {
+      elements.add(new InterceptorBinding(
+          getElementSource(), classMatcher, methodMatcher, interceptors));
+    }
+    /*end[AOP]*/
+
+    @Override
+    public void bindScope(Class<? extends Annotation> annotationType, Scope scope) {
+      elements.add(new ScopeBinding(getElementSource(), annotationType, scope));
+    }
+
+    @Override
+    @SuppressWarnings("unchecked") // it is safe to use the type literal for the raw type
+    public void requestInjection(Object instance) {
+      requestInjection((TypeLiteral<Object>) TypeLiteral.get(instance.getClass()), instance);
+    }
+
+    @Override
+    public <T> void requestInjection(TypeLiteral<T> type, T instance) {
+      elements.add(new InjectionRequest<T>(getElementSource(), MoreTypes.canonicalizeForKey(type),
+          instance));
+    }
+
+    @Override
+    public <T> MembersInjector<T> getMembersInjector(final TypeLiteral<T> typeLiteral) {
+      final MembersInjectorLookup<T> element = new MembersInjectorLookup<T>(getElementSource(),
+          MoreTypes.canonicalizeForKey(typeLiteral));
+      elements.add(element);
+      return element.getMembersInjector();
+    }
+
+    public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
+      return getMembersInjector(TypeLiteral.get(type));
+    }
+
+    public void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher, TypeListener listener) {
+      elements.add(new TypeListenerBinding(getElementSource(), listener, typeMatcher));
+    }
+    
+    public void bindListener(Matcher<? super Binding<?>> bindingMatcher,
+        ProvisionListener... listeners) {
+      elements.add(new ProvisionListenerBinding(getElementSource(), bindingMatcher, listeners));
+    }
+
+    public void requestStaticInjection(Class<?>... types) {
+      for (Class<?> type : types) {
+        elements.add(new StaticInjectionRequest(getElementSource(), type));
+      }
+    }
+
+    /**
+     * Applies all scanners to the modules we've installed. We skip certain
+     * PrivateModules because store them in more than one Modules map and only
+     * want to process them through one of the maps.  (They're stored in both
+     * maps to prevent a module from being installed more than once.)
+     */
+    void scanForAnnotatedMethods() {
+      for (ModuleAnnotatedMethodScanner scanner : scanners) {
+        // Note: we must iterate over a copy of the modules because calling install(..)
+        // will mutate modules, otherwise causing a ConcurrentModificationException.
+        for (Map.Entry<Module, ModuleInfo> entry : Maps.newLinkedHashMap(modules).entrySet()) {
+          Module module = entry.getKey();
+          ModuleInfo info = entry.getValue();
+          if (info.skipScanning) {
+            continue;
+          }
+          moduleSource = entry.getValue().moduleSource;
+          try {
+            info.binder.install(ProviderMethodsModule.forModule(module, scanner));
+          } catch(RuntimeException e) {
+            Collection<Message> messages = Errors.getMessagesFromThrowable(e);
+            if (!messages.isEmpty()) {
+              elements.addAll(messages);
+            } else {
+              addError(e);
+            }
+          }
+        }
+      }
+      moduleSource = null;
+    }
+
+    public void install(Module module) {
+      if (!modules.containsKey(module)) {
+        RecordingBinder binder = this;
+        boolean unwrapModuleSource = false;
+        // Update the module source for the new module
+        if (module instanceof ProviderMethodsModule) {
+          // There are two reason's we'd want to get the module source in a ProviderMethodsModule.
+          // ModuleAnnotatedMethodScanner lets users scan their own modules for @Provides-like
+          // bindings.  If they install the module at a top-level, then moduleSource can be null.
+          // Also, if they pass something other than 'this' to it, we'd have the wrong source.
+          Object delegate = ((ProviderMethodsModule) module).getDelegateModule();
+          if (moduleSource == null
+              || !moduleSource.getModuleClassName().equals(delegate.getClass().getName())) {
+            moduleSource = getModuleSource(delegate);
+            unwrapModuleSource = true;
+          }
+        } else {
+          moduleSource = getModuleSource(module);
+          unwrapModuleSource = true;
+        }
+        boolean skipScanning = false;
+        if (module instanceof PrivateModule) {
+          binder = (RecordingBinder) binder.newPrivateBinder();
+          // Store the module in the private binder too so we scan for it.
+          binder.modules.put(module, new ModuleInfo(binder, moduleSource, false));
+          skipScanning = true; // don't scan this module in the parent's module set.
+        }
+        // Always store this in the parent binder (even if it was a private module)
+        // so that we know not to process it again, and so that scanners inherit down.
+        modules.put(module, new ModuleInfo(binder, moduleSource, skipScanning));
+        try {
+          module.configure(binder);
+        } catch (RuntimeException e) {
+          Collection<Message> messages = Errors.getMessagesFromThrowable(e);
+          if (!messages.isEmpty()) {
+            elements.addAll(messages);
+          } else {
+            addError(e);
+          }
+        }
+        binder.install(ProviderMethodsModule.forModule(module));
+        // We are done with this module, so undo module source change
+        if (unwrapModuleSource) {
+          moduleSource = moduleSource.getParent();
+        }
+      }
+    }
+
+    public Stage currentStage() {
+      return stage;
+    }
+
+    public void addError(String message, Object... arguments) {
+      elements.add(new Message(getElementSource(), Errors.format(message, arguments)));
+    }
+
+    public void addError(Throwable t) {
+      String message = "An exception was caught and reported. Message: " + t.getMessage();
+      elements.add(new Message(ImmutableList.of((Object) getElementSource()), message, t));
+    }
+
+    public void addError(Message message) {
+      elements.add(message);
+    }
+
+    public <T> AnnotatedBindingBuilder<T> bind(Key<T> key) {
+      BindingBuilder<T> builder =
+          new BindingBuilder<T>(this, elements, getElementSource(), MoreTypes.canonicalizeKey(key));
+      return builder;
+    }
+
+    public <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
+      return bind(Key.get(typeLiteral));
+    }
+
+    public <T> AnnotatedBindingBuilder<T> bind(Class<T> type) {
+      return bind(Key.get(type));
+    }
+
+    public AnnotatedConstantBindingBuilder bindConstant() {
+      return new ConstantBindingBuilderImpl<Void>(this, elements, getElementSource());
+    }
+
+    public <T> Provider<T> getProvider(final Key<T> key) {
+      return getProvider(Dependency.get(key));
+    }
+
+    public <T> Provider<T> getProvider(final Dependency<T> dependency) {
+      final ProviderLookup<T> element = new ProviderLookup<T>(getElementSource(), dependency);
+      elements.add(element);
+      return element.getProvider();
+    }
+
+    public <T> Provider<T> getProvider(Class<T> type) {
+      return getProvider(Key.get(type));
+    }
+
+    public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
+        TypeConverter converter) {
+      elements.add(new TypeConverterBinding(getElementSource(), typeMatcher, converter));
+    }
+
+    public RecordingBinder withSource(final Object source) {            
+      return source == this.source ? this : new RecordingBinder(this, source, null);
+    }
+
+    public RecordingBinder skipSources(Class... classesToSkip) {
+      // if a source is specified explicitly, we don't need to skip sources
+      if (source != null) {
+        return this;
+      }
+
+      SourceProvider newSourceProvider = sourceProvider.plusSkippedClasses(classesToSkip);
+      return new RecordingBinder(this, null, newSourceProvider);
+    }
+
+    @Override
+    public PrivateBinder newPrivateBinder() {
+      PrivateElementsImpl privateElements = new PrivateElementsImpl(getElementSource());
+      RecordingBinder binder = new RecordingBinder(this, privateElements);
+      privateBinders.add(binder);
+      elements.add(privateElements);
+      return binder;
+    }
+
+    @Override
+    public void disableCircularProxies() {
+      elements.add(new DisableCircularProxiesOption(getElementSource()));
+    }
+
+    @Override
+    public void requireExplicitBindings() {
+      elements.add(new RequireExplicitBindingsOption(getElementSource()));
+    }
+
+    @Override
+    public void requireAtInjectOnConstructors() {
+      elements.add(new RequireAtInjectOnConstructorsOption(getElementSource()));
+    }
+
+    @Override
+    public void requireExactBindingAnnotations() {
+      elements.add(new RequireExactBindingAnnotationsOption(getElementSource()));
+    }
+
+    @Override
+    public void scanModulesForAnnotatedMethods(ModuleAnnotatedMethodScanner scanner) {
+      scanners.add(scanner);
+      elements.add(new ModuleAnnotatedMethodScannerBinding(getElementSource(), scanner));
+    }
+
+    public void expose(Key<?> key) {
+      exposeInternal(key);
+    }
+
+    @Override
+    public AnnotatedElementBuilder expose(Class<?> type) {
+      return exposeInternal(Key.get(type));
+    }
+
+    @Override
+    public AnnotatedElementBuilder expose(TypeLiteral<?> type) {
+      return exposeInternal(Key.get(type));
+    }
+
+    private <T> AnnotatedElementBuilder exposeInternal(Key<T> key) {
+      if (privateElements == null) {
+        addError("Cannot expose %s on a standard binder. "
+            + "Exposed bindings are only applicable to private binders.", key);
+        return new AnnotatedElementBuilder() {
+          @Override
+          public void annotatedWith(Class<? extends Annotation> annotationType) {}
+          @Override
+          public void annotatedWith(Annotation annotation) {}
+        };
+      }
+
+      ExposureBuilder<T> builder =
+          new ExposureBuilder<T>(this, getElementSource(), MoreTypes.canonicalizeKey(key));
+      privateElements.addExposureBuilder(builder);
+      return builder;
+    }
+
+    private ModuleSource getModuleSource(Object module) {
+      StackTraceElement[] partialCallStack;
+      if (getIncludeStackTraceOption() == IncludeStackTraceOption.COMPLETE) {
+        partialCallStack = getPartialCallStack(new Throwable().getStackTrace());
+      } else {
+        partialCallStack = new StackTraceElement[0];
+      }
+      if (moduleSource == null) {
+        return new ModuleSource(module, partialCallStack);
+      }
+      return moduleSource.createChild(module, partialCallStack);
+    }
+
+    private ElementSource getElementSource() {
+      // Full call stack
+      StackTraceElement[] callStack = null;
+      // The call stack starts from current top module configure and ends at this method caller
+      StackTraceElement[] partialCallStack = new StackTraceElement[0];
+      // The element original source
+      ElementSource originalSource = null;
+      // The element declaring source
+      Object declaringSource = source;
+      if (declaringSource instanceof ElementSource) {
+        originalSource = (ElementSource) declaringSource;
+        declaringSource = originalSource.getDeclaringSource();
+      }
+      IncludeStackTraceOption stackTraceOption = getIncludeStackTraceOption();
+      if (stackTraceOption == IncludeStackTraceOption.COMPLETE ||
+          (stackTraceOption == IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE
+          && declaringSource == null)) {
+        callStack = new Throwable().getStackTrace();
+      }
+      if (stackTraceOption == IncludeStackTraceOption.COMPLETE) {
+        partialCallStack = getPartialCallStack(callStack);
+      }
+      if (declaringSource == null) {
+        // So 'source' and 'originalSource' are null otherwise declaringSource has some value
+        if (stackTraceOption == IncludeStackTraceOption.COMPLETE ||
+            stackTraceOption == IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE) {
+          // With the above conditions and assignments 'callStack' is non-null
+          declaringSource = sourceProvider.get(callStack);
+        } else { // or if (stackTraceOption == IncludeStackTraceOptions.OFF)
+          // As neither 'declaring source' nor 'call stack' is available use 'module source'
+          declaringSource = sourceProvider.getFromClassNames(moduleSource.getModuleClassNames());
+        }
+      }
+      // Build the binding call stack
+      return new ElementSource(
+          originalSource, declaringSource, moduleSource, partialCallStack);
+    }
+
+    /**
+     * Removes the {@link #moduleSource} call stack from the beginning of current call stack. It
+     * also removes the last two elements in order to make {@link #install(Module)} the last call
+     * in the call stack.
+     */
+    private StackTraceElement[] getPartialCallStack(StackTraceElement[] callStack) {
+      int toSkip = 0;
+      if (moduleSource != null) {
+        toSkip = moduleSource.getStackTraceSize();
+      }
+      // -1 for skipping 'getModuleSource' and 'getElementSource' calls
+      int chunkSize = callStack.length - toSkip - 1;
+
+      StackTraceElement[] partialCallStack = new StackTraceElement[chunkSize];
+      System.arraycopy(callStack, 1, partialCallStack, 0, chunkSize);
+      return partialCallStack;
+    }
+
+    @Override public String toString() {
+      return "Binder";
+    }
+  }
+}
diff --git a/core/src/com/google/inject/spi/ExposedBinding.java b/core/src/com/google/inject/spi/ExposedBinding.java
new file mode 100644
index 0000000..16a569e
--- /dev/null
+++ b/core/src/com/google/inject/spi/ExposedBinding.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+
+/**
+ * A binding to a key exposed from an enclosed private environment.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface ExposedBinding<T> extends Binding<T>, HasDependencies {
+
+  /**
+   * Returns the enclosed environment that holds the original binding.
+   */
+  PrivateElements getPrivateElements();
+
+  /**
+   * Unsupported. Always throws {@link UnsupportedOperationException}.
+   */
+  void applyTo(Binder binder);
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/HasDependencies.java b/core/src/com/google/inject/spi/HasDependencies.java
new file mode 100644
index 0000000..77a5523
--- /dev/null
+++ b/core/src/com/google/inject/spi/HasDependencies.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import java.util.Set;
+
+/**
+ * Implemented by {@link com.google.inject.Binding bindings}, {@link com.google.inject.Provider
+ * providers} and instances that expose their dependencies explicitly.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface HasDependencies {
+
+  /**
+   * Returns the known dependencies for this type. If this has dependencies whose values are not
+   * known statically, a dependency for the {@link com.google.inject.Injector Injector} will be
+   * included in the returned set.
+   * 
+   * @return a possibly empty set
+   */
+  Set<Dependency<?>> getDependencies();
+}
diff --git a/core/src/com/google/inject/spi/InjectionListener.java b/core/src/com/google/inject/spi/InjectionListener.java
new file mode 100644
index 0000000..14cf00d
--- /dev/null
+++ b/core/src/com/google/inject/spi/InjectionListener.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.google.inject.spi;
+
+/**
+ * Listens for injections into instances of type {@code I}. Useful for performing further
+ * injections, post-injection initialization, and more.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface InjectionListener<I> {
+
+  /**
+   * Invoked by Guice after it injects the fields and methods of instance.
+   *
+   * @param injectee instance that Guice injected dependencies into
+   */
+  void afterInjection(I injectee);
+}
diff --git a/core/src/com/google/inject/spi/InjectionPoint.java b/core/src/com/google/inject/spi/InjectionPoint.java
new file mode 100644
index 0000000..267e0ab
--- /dev/null
+++ b/core/src/com/google/inject/spi/InjectionPoint.java
@@ -0,0 +1,875 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.inject.internal.MoreTypes.getRawType;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.Annotations;
+import com.google.inject.internal.Errors;
+import com.google.inject.internal.ErrorsException;
+import com.google.inject.internal.Nullability;
+import com.google.inject.internal.util.Classes;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A constructor, field or method that can receive injections. Typically this is a member with the
+ * {@literal @}{@link Inject} annotation. For non-private, no argument constructors, the member may
+ * omit the annotation.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @since 2.0
+ */
+public final class InjectionPoint {
+  
+  private static final Logger logger = Logger.getLogger(InjectionPoint.class.getName());
+
+  private final boolean optional;
+  private final Member member;
+  private final TypeLiteral<?> declaringType;
+  private final ImmutableList<Dependency<?>> dependencies;
+
+  InjectionPoint(TypeLiteral<?> declaringType, Method method, boolean optional) {
+    this.member = method;
+    this.declaringType = declaringType;
+    this.optional = optional;
+    this.dependencies = forMember(method, declaringType, method.getParameterAnnotations());
+  }
+
+  InjectionPoint(TypeLiteral<?> declaringType, Constructor<?> constructor) {
+    this.member = constructor;
+    this.declaringType = declaringType;
+    this.optional = false;
+    this.dependencies = forMember(
+        constructor, declaringType, constructor.getParameterAnnotations());
+  }
+
+  InjectionPoint(TypeLiteral<?> declaringType, Field field, boolean optional) {
+    this.member = field;
+    this.declaringType = declaringType;
+    this.optional = optional;
+
+    Annotation[] annotations = field.getAnnotations();
+
+    Errors errors = new Errors(field);
+    Key<?> key = null;
+    try {
+      key = Annotations.getKey(declaringType.getFieldType(field), field, annotations, errors);
+    } catch (ConfigurationException e) {
+      errors.merge(e.getErrorMessages());
+    } catch (ErrorsException e) {
+      errors.merge(e.getErrors());
+    }
+    errors.throwConfigurationExceptionIfErrorsExist();
+
+    this.dependencies = ImmutableList.<Dependency<?>>of(
+        newDependency(key, Nullability.allowsNull(annotations), -1));
+  }
+
+  private ImmutableList<Dependency<?>> forMember(Member member, TypeLiteral<?> type,
+      Annotation[][] paramterAnnotations) {
+    Errors errors = new Errors(member);
+    Iterator<Annotation[]> annotationsIterator = Arrays.asList(paramterAnnotations).iterator();
+
+    List<Dependency<?>> dependencies = Lists.newArrayList();
+    int index = 0;
+
+    for (TypeLiteral<?> parameterType : type.getParameterTypes(member)) {
+      try {
+        Annotation[] parameterAnnotations = annotationsIterator.next();
+        Key<?> key = Annotations.getKey(parameterType, member, parameterAnnotations, errors);
+        dependencies.add(newDependency(key, Nullability.allowsNull(parameterAnnotations), index));
+        index++;
+      } catch (ConfigurationException e) {
+        errors.merge(e.getErrorMessages());
+      } catch (ErrorsException e) {
+        errors.merge(e.getErrors());
+      }
+    }
+
+    errors.throwConfigurationExceptionIfErrorsExist();
+    return ImmutableList.copyOf(dependencies);
+  }
+
+  // This metohd is necessary to create a Dependency<T> with proper generic type information
+  private <T> Dependency<T> newDependency(Key<T> key, boolean allowsNull, int parameterIndex) {
+    return new Dependency<T>(this, key, allowsNull, parameterIndex);
+  }
+
+  /**
+   * Returns the injected constructor, field, or method.
+   */
+  public Member getMember() {
+    // TODO: Don't expose the original member (which probably has setAccessible(true)).
+    return member;
+  }
+
+  /**
+   * Returns the dependencies for this injection point. If the injection point is for a method or
+   * constructor, the dependencies will correspond to that member's parameters. Field injection
+   * points always have a single dependency for the field itself.
+   *
+   * @return a possibly-empty list
+   */
+  public List<Dependency<?>> getDependencies() {
+    return dependencies;
+  }
+
+  /**
+   * Returns true if this injection point shall be skipped if the injector cannot resolve bindings
+   * for all required dependencies. Both explicit bindings (as specified in a module), and implicit
+   * bindings ({@literal @}{@link com.google.inject.ImplementedBy ImplementedBy}, default
+   * constructors etc.) may be used to satisfy optional injection points.
+   */
+  public boolean isOptional() {
+    return optional;
+  }
+  
+  /**
+   * Returns true if the element is annotated with {@literal @}{@link Toolable}.
+   * 
+   * @since 3.0
+   */
+  public boolean isToolable() {
+    return ((AnnotatedElement)member).isAnnotationPresent(Toolable.class);
+  }
+
+  /**
+   * Returns the generic type that defines this injection point. If the member exists on a
+   * parameterized type, the result will include more type information than the member's {@link
+   * Member#getDeclaringClass() raw declaring class}.
+   * 
+   * @since 3.0
+   */
+  public TypeLiteral<?> getDeclaringType() {
+    return declaringType;
+  }
+
+  @Override public boolean equals(Object o) {
+    return o instanceof InjectionPoint
+        && member.equals(((InjectionPoint) o).member)
+        && declaringType.equals(((InjectionPoint) o).declaringType);
+  }
+
+  @Override public int hashCode() {
+    return member.hashCode() ^ declaringType.hashCode();
+  }
+
+  @Override public String toString() {
+    return Classes.toString(member);
+  }
+
+  /**
+   * Returns a new injection point for the specified constructor. If the declaring type of {@code
+   * constructor} is parameterized (such as {@code List<T>}), prefer the overload that includes a
+   * type literal.
+   *
+   * @param constructor any single constructor present on {@code type}.
+   * 
+   * @since 3.0
+   */
+  public static <T> InjectionPoint forConstructor(Constructor<T> constructor) {
+    return new InjectionPoint(TypeLiteral.get(constructor.getDeclaringClass()), constructor);
+  }
+
+  /**
+   * Returns a new injection point for the specified constructor of {@code type}.
+   *
+   * @param constructor any single constructor present on {@code type}.
+   * @param type the concrete type that defines {@code constructor}.
+   * 
+   * @since 3.0
+   */
+  public static <T> InjectionPoint forConstructor(
+      Constructor<T> constructor, TypeLiteral<? extends T> type) {
+    if (type.getRawType() != constructor.getDeclaringClass()) {
+      new Errors(type)
+          .constructorNotDefinedByType(constructor, type)
+          .throwConfigurationExceptionIfErrorsExist();
+    }
+
+    return new InjectionPoint(type, constructor);
+  }
+
+  /**
+   * Returns a new injection point for the injectable constructor of {@code type}.
+   *
+   * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
+   *     or a no-arguments constructor that is not private.
+   * @throws ConfigurationException if there is no injectable constructor, more than one injectable
+   *     constructor, or if parameters of the injectable constructor are malformed, such as a
+   *     parameter with multiple binding annotations.
+   */
+  public static InjectionPoint forConstructorOf(TypeLiteral<?> type) {
+    Class<?> rawType = getRawType(type.getType());
+    Errors errors = new Errors(rawType);
+
+    Constructor<?> injectableConstructor = null;
+    for (Constructor<?> constructor : rawType.getDeclaredConstructors()) {
+
+      boolean optional;
+      Inject guiceInject = constructor.getAnnotation(Inject.class);
+      if (guiceInject == null) {
+        javax.inject.Inject javaxInject = constructor.getAnnotation(javax.inject.Inject.class);
+        if (javaxInject == null) {
+          continue;
+        }
+        optional = false;
+      } else {
+        optional = guiceInject.optional();
+      }
+
+      if (optional) {
+        errors.optionalConstructor(constructor);
+      }
+
+      if (injectableConstructor != null) {
+        errors.tooManyConstructors(rawType);
+      }
+
+      injectableConstructor = constructor;
+      checkForMisplacedBindingAnnotations(injectableConstructor, errors);
+    }
+
+    errors.throwConfigurationExceptionIfErrorsExist();
+
+    if (injectableConstructor != null) {
+      return new InjectionPoint(type, injectableConstructor);
+    }
+
+    // If no annotated constructor is found, look for a no-arg constructor instead.
+    try {
+      Constructor<?> noArgConstructor = rawType.getDeclaredConstructor();
+
+      // Disallow private constructors on non-private classes (unless they have @Inject)
+      if (Modifier.isPrivate(noArgConstructor.getModifiers())
+          && !Modifier.isPrivate(rawType.getModifiers())) {
+        errors.missingConstructor(rawType);
+        throw new ConfigurationException(errors.getMessages());
+      }
+
+      checkForMisplacedBindingAnnotations(noArgConstructor, errors);
+      return new InjectionPoint(type, noArgConstructor);
+    } catch (NoSuchMethodException e) {
+      errors.missingConstructor(rawType);
+      throw new ConfigurationException(errors.getMessages());
+    }
+  }
+
+  /**
+   * Returns a new injection point for the injectable constructor of {@code type}.
+   *
+   * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
+   *     or a no-arguments constructor that is not private.
+   * @throws ConfigurationException if there is no injectable constructor, more than one injectable
+   *     constructor, or if parameters of the injectable constructor are malformed, such as a
+   *     parameter with multiple binding annotations.
+   */
+  public static InjectionPoint forConstructorOf(Class<?> type) {
+    return forConstructorOf(TypeLiteral.get(type));
+  }
+
+  /**
+   * Returns a new injection point for the specified method of {@code type}.
+   * This is useful for extensions that need to build dependency graphs from
+   * arbitrary methods.
+   *
+   * @param method any single method present on {@code type}.
+   * @param type the concrete type that defines {@code method}.
+   *
+   * @since 4.0
+   */
+  public static <T> InjectionPoint forMethod(Method method, TypeLiteral<T> type) {
+    return new InjectionPoint(type, method, false);
+  }
+
+  /**
+   * Returns all static method and field injection points on {@code type}.
+   *
+   * @return a possibly empty set of injection points. The set has a specified iteration order. All
+   *      fields are returned and then all methods. Within the fields, supertype fields are returned
+   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+   *      a field with multiple binding annotations. The exception's {@link
+   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+   *      of the valid injection points.
+   */
+  public static Set<InjectionPoint> forStaticMethodsAndFields(TypeLiteral<?> type) {
+    Errors errors = new Errors();
+    
+    Set<InjectionPoint> result;
+    
+    if (type.getRawType().isInterface()) {
+      errors.staticInjectionOnInterface(type.getRawType());
+      result = null;
+    } else {
+      result = getInjectionPoints(type, true, errors);
+    }
+    
+    if (errors.hasErrors()) {
+      throw new ConfigurationException(errors.getMessages()).withPartialValue(result);
+    }
+    return result;
+  }
+
+  /**
+   * Returns all static method and field injection points on {@code type}.
+   *
+   * @return a possibly empty set of injection points. The set has a specified iteration order. All
+   *      fields are returned and then all methods. Within the fields, supertype fields are returned
+   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+   *      a field with multiple binding annotations. The exception's {@link
+   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+   *      of the valid injection points.
+   */
+  public static Set<InjectionPoint> forStaticMethodsAndFields(Class<?> type) {
+    return forStaticMethodsAndFields(TypeLiteral.get(type));
+  }
+
+  /**
+   * Returns all instance method and field injection points on {@code type}.
+   *
+   * @return a possibly empty set of injection points. The set has a specified iteration order. All
+   *      fields are returned and then all methods. Within the fields, supertype fields are returned
+   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+   *      a field with multiple binding annotations. The exception's {@link
+   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+   *      of the valid injection points.
+   */
+  public static Set<InjectionPoint> forInstanceMethodsAndFields(TypeLiteral<?> type) {
+    Errors errors = new Errors();
+    Set<InjectionPoint> result = getInjectionPoints(type, false, errors);
+    if (errors.hasErrors()) {
+      throw new ConfigurationException(errors.getMessages()).withPartialValue(result);
+    }
+    return result;
+  }
+
+  /**
+   * Returns all instance method and field injection points on {@code type}.
+   *
+   * @return a possibly empty set of injection points. The set has a specified iteration order. All
+   *      fields are returned and then all methods. Within the fields, supertype fields are returned
+   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+   *      a field with multiple binding annotations. The exception's {@link
+   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+   *      of the valid injection points.
+   */
+  public static Set<InjectionPoint> forInstanceMethodsAndFields(Class<?> type) {
+    return forInstanceMethodsAndFields(TypeLiteral.get(type));
+  }
+
+  /**
+   * Returns true if the binding annotation is in the wrong place.
+   */
+  private static boolean checkForMisplacedBindingAnnotations(Member member, Errors errors) {
+    Annotation misplacedBindingAnnotation = Annotations.findBindingAnnotation(
+        errors, member, ((AnnotatedElement) member).getAnnotations());
+    if (misplacedBindingAnnotation == null) {
+      return false;
+    }
+
+    // don't warn about misplaced binding annotations on methods when there's a field with the same
+    // name. In Scala, fields always get accessor methods (that we need to ignore). See bug 242.
+    if (member instanceof Method) {
+      try {
+        if (member.getDeclaringClass().getDeclaredField(member.getName()) != null) {
+          return false;
+        }
+      } catch (NoSuchFieldException ignore) {
+      }
+    }
+
+    errors.misplacedBindingAnnotation(member, misplacedBindingAnnotation);
+    return true;
+  }
+
+  /**
+   * Node in the doubly-linked list of injectable members (fields and methods).
+   */
+  static abstract class InjectableMember {
+    final TypeLiteral<?> declaringType;
+    final boolean optional;
+    final boolean jsr330;
+    InjectableMember previous;
+    InjectableMember next;
+
+    InjectableMember(TypeLiteral<?> declaringType, Annotation atInject) {
+      this.declaringType = declaringType;
+
+      if (atInject.annotationType() == javax.inject.Inject.class) {
+        optional = false;
+        jsr330 = true;
+        return;
+      }
+
+      jsr330 = false;
+      optional = ((Inject) atInject).optional();
+    }
+
+    abstract InjectionPoint toInjectionPoint();
+  }
+
+  static class InjectableField extends InjectableMember {
+    final Field field;
+    InjectableField(TypeLiteral<?> declaringType, Field field,
+        Annotation atInject) {
+      super(declaringType, atInject);
+      this.field = field;
+    }
+
+    @Override
+    InjectionPoint toInjectionPoint() {
+      return new InjectionPoint(declaringType, field, optional);
+    }
+  }
+
+  static class InjectableMethod extends InjectableMember {
+    final Method method;
+    /**
+     * true if this method overrode a method that was annotated
+     * with com.google.inject.Inject.  used to allow different
+     * override behavior for guice inject vs javax.inject.Inject
+     */
+    boolean overrodeGuiceInject;
+    InjectableMethod(TypeLiteral<?> declaringType, Method method,
+        Annotation atInject) {
+      super(declaringType, atInject);
+      this.method = method;
+    }
+
+    @Override
+    InjectionPoint toInjectionPoint() {
+      return new InjectionPoint(declaringType, method, optional);
+    }
+
+    public boolean isFinal() {
+      return Modifier.isFinal(method.getModifiers());
+    }
+  }
+
+  static Annotation getAtInject(AnnotatedElement member) {
+    Annotation a = member.getAnnotation(javax.inject.Inject.class);
+    return a == null ? member.getAnnotation(Inject.class) : a;
+  }
+
+  /**
+   * Linked list of injectable members.
+   */
+  static class InjectableMembers {
+    InjectableMember head;
+    InjectableMember tail;
+
+    void add(InjectableMember member) {
+      if (head == null) {
+        head = tail = member;
+      } else {
+        member.previous = tail;
+        tail.next = member;
+        tail = member;
+      }
+    }
+
+    void remove(InjectableMember member) {
+      if (member.previous != null) {
+        member.previous.next = member.next;
+      }
+      if (member.next != null) {
+        member.next.previous = member.previous;
+      }
+      if (head == member) {
+        head = member.next;
+      }
+      if (tail == member) {
+        tail = member.previous;
+      }
+    }
+
+    boolean isEmpty() {
+      return head == null;
+    }
+  }
+
+  /** Position in type hierarchy. */
+  enum Position {
+    TOP, // No need to check for overridden methods
+    MIDDLE,
+    BOTTOM // Methods won't be overridden
+  }
+
+  /**
+   * Keeps track of injectable methods so we can remove methods that get overridden in O(1) time.
+   * Uses our position in the type hierarchy to perform optimizations.
+   */
+  static class OverrideIndex {
+    final InjectableMembers injectableMembers;
+    Map<Signature, List<InjectableMethod>> bySignature;
+    Position position = Position.TOP;
+
+    OverrideIndex(InjectableMembers injectableMembers) {
+      this.injectableMembers = injectableMembers;
+    }
+
+    /* Caches the signature for the last method. */
+    Method lastMethod;
+    Signature lastSignature;
+
+    /**
+     * Removes a method overridden by the given method, if present. In order to
+     * remain backwards compatible with prior Guice versions, this will *not*
+     * remove overridden methods if 'alwaysRemove' is false and the overridden
+     * signature was annotated with a com.google.inject.Inject.
+     * 
+     * @param method
+     *          The method used to determine what is overridden and should be
+     *          removed.
+     * @param alwaysRemove
+     *          true if overridden methods should be removed even if they were
+     *          guice @Inject
+     * @param injectableMethod
+     *          if this method overrode any guice @Inject methods,
+     *          {@link InjectableMethod#overrodeGuiceInject} is set to true
+     */
+    boolean removeIfOverriddenBy(Method method, boolean alwaysRemove, 
+        InjectableMethod injectableMethod) {
+      if (position == Position.TOP) {
+        // If we're at the top of the hierarchy, there's nothing to override.
+        return false;
+      }
+
+      if (bySignature == null) {
+        // We encountered a method in a subclass. Time to index the
+        // methods in the parent class.
+        bySignature = new HashMap<Signature, List<InjectableMethod>>();
+        for (InjectableMember member = injectableMembers.head; member != null;
+            member = member.next) {
+          if (!(member instanceof InjectableMethod)) continue;
+          InjectableMethod im = (InjectableMethod) member;
+          if (im.isFinal()) continue;
+          List<InjectableMethod> methods = new ArrayList<InjectableMethod>();
+          methods.add(im);
+          bySignature.put(new Signature(im.method), methods);
+        }
+      }
+
+      lastMethod = method;
+      Signature signature = lastSignature = new Signature(method);
+      List<InjectableMethod> methods = bySignature.get(signature);
+      boolean removed = false;
+      if (methods != null) {
+        for (Iterator<InjectableMethod> iterator = methods.iterator();
+            iterator.hasNext();) {
+          InjectableMethod possiblyOverridden = iterator.next();
+          if (overrides(method, possiblyOverridden.method)) {
+            boolean wasGuiceInject =
+              !possiblyOverridden.jsr330 || possiblyOverridden.overrodeGuiceInject;
+            if(injectableMethod != null) {
+              injectableMethod.overrodeGuiceInject = wasGuiceInject;
+            }
+            // Only actually remove the methods if we want to force
+            // remove or if the signature never specified @com.google.inject.Inject
+            // somewhere.
+            if(alwaysRemove || !wasGuiceInject) {
+              removed = true;
+              iterator.remove();
+              injectableMembers.remove(possiblyOverridden);
+            }
+          }
+        }
+      }
+      return removed;
+    }
+
+    /**
+     * Adds the given method to the list of injection points. Keeps track of it in this index
+     * in case it gets overridden.
+     */
+    void add(InjectableMethod injectableMethod) {
+      injectableMembers.add(injectableMethod);
+      if (position == Position.BOTTOM
+          || injectableMethod.isFinal()) {
+        // This method can't be overridden, so there's no need to index it.
+        return;
+      }
+      if (bySignature != null) {
+        // Try to reuse the signature we created during removal
+        Signature signature = injectableMethod.method == lastMethod
+            ? lastSignature : new Signature(injectableMethod.method);
+        List<InjectableMethod> methods = bySignature.get(signature);
+        if (methods == null) {
+          methods = new ArrayList<InjectableMethod>();
+          bySignature.put(signature, methods);
+        }
+        methods.add(injectableMethod);
+      }
+    }
+  }
+
+  /**
+   * Returns an ordered, immutable set of injection points for the given type. Members in
+   * superclasses come before members in subclasses. Within a class, fields come before methods.
+   * Overridden methods are filtered out.
+   *
+   * @param statics true is this method should return static members, false for instance members
+   * @param errors used to record errors
+   */
+  private static Set<InjectionPoint> getInjectionPoints(final TypeLiteral<?> type,
+      boolean statics, Errors errors) {
+    InjectableMembers injectableMembers = new InjectableMembers();
+    OverrideIndex overrideIndex = null;
+
+    List<TypeLiteral<?>> hierarchy = hierarchyFor(type);
+    int topIndex = hierarchy.size() - 1;
+    for (int i = topIndex; i >= 0; i--) {
+      if (overrideIndex != null && i < topIndex) {
+        // Knowing the position within the hierarchy helps us make optimizations.
+        if (i == 0) {
+          overrideIndex.position = Position.BOTTOM;
+        } else {
+          overrideIndex.position = Position.MIDDLE;
+        }
+      }
+
+      TypeLiteral<?> current = hierarchy.get(i);
+
+      for (Field field : current.getRawType().getDeclaredFields()) {
+        if (Modifier.isStatic(field.getModifiers()) == statics) {
+          Annotation atInject = getAtInject(field);
+          if (atInject != null) {
+            InjectableField injectableField = new InjectableField(current, field, atInject);
+            if (injectableField.jsr330 && Modifier.isFinal(field.getModifiers())) {
+              errors.cannotInjectFinalField(field);
+            }
+            injectableMembers.add(injectableField);
+          }
+        }
+      }
+
+      for (Method method : current.getRawType().getDeclaredMethods()) {
+        if (isEligibleForInjection(method, statics)) {
+          Annotation atInject = getAtInject(method);
+          if (atInject != null) {
+            InjectableMethod injectableMethod = new InjectableMethod(
+                current, method, atInject);
+            if (checkForMisplacedBindingAnnotations(method, errors)
+                || !isValidMethod(injectableMethod, errors)) {
+              if (overrideIndex != null) {
+                boolean removed = overrideIndex.removeIfOverriddenBy(method, false, injectableMethod);
+                if(removed) {
+                  logger.log(Level.WARNING, "Method: {0} is not a valid injectable method ("
+                      + "because it either has misplaced binding annotations "
+                      + "or specifies type parameters) but is overriding a method that is valid. "
+                      + "Because it is not valid, the method will not be injected. "
+                      + "To fix this, make the method a valid injectable method.", method);
+                }
+              }
+              continue;
+            }
+            if (statics) {
+              injectableMembers.add(injectableMethod);
+            } else {
+              if (overrideIndex == null) {
+                /*
+                 * Creating the override index lazily means that the first type in the hierarchy
+                 * with injectable methods (not necessarily the top most type) will be treated as
+                 * the TOP position and will enjoy the same optimizations (no checks for overridden
+                 * methods, etc.).
+                 */
+                overrideIndex = new OverrideIndex(injectableMembers);
+              } else {
+                // Forcibly remove the overriden method, otherwise we'll inject
+                // it twice.
+                overrideIndex.removeIfOverriddenBy(method, true, injectableMethod);
+              }
+              overrideIndex.add(injectableMethod);
+            }
+          } else {
+            if(overrideIndex != null) {
+              boolean removed = overrideIndex.removeIfOverriddenBy(method, false, null);
+              if(removed) {
+                logger.log(Level.WARNING, "Method: {0} is not annotated with @Inject but "
+                    + "is overriding a method that is annotated with @javax.inject.Inject.  Because "
+                    + "it is not annotated with @Inject, the method will not be injected. "
+                    + "To fix this, annotate the method with @Inject.", method);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    if (injectableMembers.isEmpty()) {
+      return Collections.emptySet();
+    }
+
+    ImmutableSet.Builder<InjectionPoint> builder = ImmutableSet.builder();
+    for (InjectableMember im = injectableMembers.head; im != null;
+        im = im.next) {
+      try {
+        builder.add(im.toInjectionPoint());
+      } catch (ConfigurationException ignorable) {
+        if (!im.optional) {
+          errors.merge(ignorable.getErrorMessages());
+        }
+      }
+    }
+    return builder.build();
+  }
+
+  /** 
+   * Returns true if the method is eligible to be injected.  This is different than
+   * {@link #isValidMethod}, because ineligibility will not drop a method
+   * from being injected if a superclass was eligible & valid. 
+   * Bridge & synthetic methods are excluded from eligibility for two reasons:
+   * 
+   * <p>Prior to Java8, javac would generate these methods in subclasses without
+   * annotations, which means this would accidentally stop injecting a method
+   * annotated with {@link javax.inject.Inject}, since the spec says to stop
+   * injecting if a subclass isn't annotated with it.
+   * 
+   * <p>Starting at Java8, javac copies the annotations to the generated subclass
+   * method, except it leaves out the generic types.  If this considered it a valid
+   * injectable method, this would eject the parent's overridden method that had the
+   * proper generic types, and would use invalid injectable parameters as a result.
+   * 
+   * <p>The fix for both is simply to ignore these synthetic bridge methods.
+   */
+  private static boolean isEligibleForInjection(Method method, boolean statics) {
+    return Modifier.isStatic(method.getModifiers()) == statics
+        && !method.isBridge()
+        && !method.isSynthetic();
+  }
+
+  private static boolean isValidMethod(InjectableMethod injectableMethod,
+      Errors errors) {
+    boolean result = true;
+    if (injectableMethod.jsr330) {
+      Method method = injectableMethod.method;
+      if (Modifier.isAbstract(method.getModifiers())) {
+        errors.cannotInjectAbstractMethod(method);
+        result = false;
+      }
+      if (method.getTypeParameters().length > 0) {
+        errors.cannotInjectMethodWithTypeParameters(method);
+        result = false;
+      }
+    }
+    return result;
+  }
+
+  private static List<TypeLiteral<?>> hierarchyFor(TypeLiteral<?> type) {
+    List<TypeLiteral<?>> hierarchy = new ArrayList<TypeLiteral<?>>();
+    TypeLiteral<?> current = type;
+    while (current.getRawType() != Object.class) {
+      hierarchy.add(current);
+      current = current.getSupertype(current.getRawType().getSuperclass());
+    }
+    return hierarchy;
+  }
+
+  /**
+   * Returns true if a overrides b. Assumes signatures of a and b are the same and a's declaring
+   * class is a subclass of b's declaring class.
+   */
+  private static boolean overrides(Method a, Method b) {
+    // See JLS section 8.4.8.1
+    int modifiers = b.getModifiers();
+    if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
+      return true;
+    }
+    if (Modifier.isPrivate(modifiers)) {
+      return false;
+    }
+    // b must be package-private
+    return a.getDeclaringClass().getPackage().equals(b.getDeclaringClass().getPackage());
+  }
+
+  /**
+   * A method signature. Used to handle method overridding.
+   */
+  static class Signature {
+
+    final String name;
+    final Class[] parameterTypes;
+    final int hash;
+
+    Signature(Method method) {
+      this.name = method.getName();
+      this.parameterTypes = method.getParameterTypes();
+
+      int h = name.hashCode();
+      h = h * 31 + parameterTypes.length;
+      for (Class parameterType : parameterTypes) {
+        h = h * 31 + parameterType.hashCode();
+      }
+      this.hash = h;
+    }
+
+    @Override public int hashCode() {
+      return this.hash;
+    }
+
+    @Override public boolean equals(Object o) {
+      if (!(o instanceof Signature)) {
+        return false;
+      }
+
+      Signature other = (Signature) o;
+      if (!name.equals(other.name)) {
+        return false;
+      }
+
+      if (parameterTypes.length != other.parameterTypes.length) {
+        return false;
+      }
+
+      for (int i = 0; i < parameterTypes.length; i++) {
+        if (parameterTypes[i] != other.parameterTypes[i]) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+  }
+}
diff --git a/core/src/com/google/inject/spi/InjectionRequest.java b/core/src/com/google/inject/spi/InjectionRequest.java
new file mode 100644
index 0000000..f80e37a
--- /dev/null
+++ b/core/src/com/google/inject/spi/InjectionRequest.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+import com.google.inject.ConfigurationException;
+import com.google.inject.TypeLiteral;
+
+import java.util.Set;
+
+/**
+ * A request to inject the instance fields and methods of an instance. Requests are created
+ * explicitly in a module using {@link com.google.inject.Binder#requestInjection(Object)
+ * requestInjection()} statements:
+ * <pre>
+ *     requestInjection(serviceInstance);</pre>
+ *
+ * @author mikeward@google.com (Mike Ward)
+ * @since 2.0
+ */
+public final class InjectionRequest<T> implements Element {
+
+  private final Object source;
+  private final TypeLiteral<T> type;
+  private final T instance;
+
+  public InjectionRequest(Object source, TypeLiteral<T> type, T instance) {
+    this.source = checkNotNull(source, "source");
+    this.type = checkNotNull(type, "type");
+    this.instance = checkNotNull(instance, "instance");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public T getInstance() {
+    return instance;
+  }
+
+  public TypeLiteral<T> getType() {
+    return type;
+  }
+
+  /**
+   * Returns the instance methods and fields of {@code instance} that will be injected to fulfill
+   * this request.
+   *
+   * @return a possibly empty set of injection points. The set has a specified iteration order. All
+   *      fields are returned and then all methods. Within the fields, supertype fields are returned
+   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+   * @throws ConfigurationException if there is a malformed injection point on the class of {@code
+   *      instance}, such as a field with multiple binding annotations. The exception's {@link
+   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+   *      of the valid injection points.
+   */
+  public Set<InjectionPoint> getInjectionPoints() throws ConfigurationException {
+    return InjectionPoint.forInstanceMethodsAndFields(instance.getClass());
+  }
+
+  public <R> R acceptVisitor(ElementVisitor<R> visitor) {
+    return visitor.visit(this);
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).requestInjection(type, instance);
+  }
+}
diff --git a/core/src/com/google/inject/spi/InstanceBinding.java b/core/src/com/google/inject/spi/InstanceBinding.java
new file mode 100644
index 0000000..2e2270c
--- /dev/null
+++ b/core/src/com/google/inject/spi/InstanceBinding.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+
+import java.util.Set;
+
+/**
+ * A binding to a single instance. The same instance is returned for every injection.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface InstanceBinding<T> extends Binding<T>, HasDependencies {
+
+  /**
+   * Returns the user-supplied instance.
+   */
+  T getInstance();
+
+  /**
+   * Returns the field and method injection points of the instance, injected at injector-creation
+   * time only.
+   *
+   * @return a possibly empty set
+   */
+  Set<InjectionPoint> getInjectionPoints();
+
+}
diff --git a/core/src/com/google/inject/spi/InterceptorBinding.java b/core/src/com/google/inject/spi/InterceptorBinding.java
new file mode 100644
index 0000000..a16e701
--- /dev/null
+++ b/core/src/com/google/inject/spi/InterceptorBinding.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Binder;
+import com.google.inject.matcher.Matcher;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Registration of interceptors for matching methods of matching classes. Instances are created
+ * explicitly in a module using {@link com.google.inject.Binder#bindInterceptor(
+ * Matcher, Matcher, MethodInterceptor[]) bindInterceptor()} statements:
+ * <pre>
+ *     bindInterceptor(Matchers.subclassesOf(MyAction.class),
+ *         Matchers.annotatedWith(Transactional.class),
+ *         new MyTransactionInterceptor());</pre>
+ *
+ * or from an injectable type listener using {@link TypeEncounter#bindInterceptor(Matcher,
+ * org.aopalliance.intercept.MethodInterceptor[]) TypeEncounter.bindInterceptor()}.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class InterceptorBinding implements Element {
+  private final Object source;
+  private final Matcher<? super Class<?>> classMatcher;
+  private final Matcher<? super Method> methodMatcher;
+  private final ImmutableList<MethodInterceptor> interceptors;
+
+  InterceptorBinding(
+      Object source,
+      Matcher<? super Class<?>> classMatcher,
+      Matcher<? super Method> methodMatcher,
+      MethodInterceptor[] interceptors) {
+    this.source = checkNotNull(source, "source");
+    this.classMatcher = checkNotNull(classMatcher, "classMatcher");
+    this.methodMatcher = checkNotNull(methodMatcher, "methodMatcher");
+    this.interceptors = ImmutableList.copyOf(interceptors);
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public Matcher<? super Class<?>> getClassMatcher() {
+    return classMatcher;
+  }
+
+  public Matcher<? super Method> getMethodMatcher() {
+    return methodMatcher;
+  }
+
+  public List<MethodInterceptor> getInterceptors() {
+    return interceptors;
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).bindInterceptor(classMatcher, methodMatcher,
+        interceptors.toArray(new MethodInterceptor[interceptors.size()]));
+  }
+}
diff --git a/core/src/com/google/inject/spi/LinkedKeyBinding.java b/core/src/com/google/inject/spi/LinkedKeyBinding.java
new file mode 100644
index 0000000..7b823a6
--- /dev/null
+++ b/core/src/com/google/inject/spi/LinkedKeyBinding.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Key;
+
+/**
+ * A binding to a linked key. The other key's binding is used to resolve injections.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface LinkedKeyBinding<T> extends Binding<T> {
+
+  /**
+   * Returns the linked key used to resolve injections. That binding can be retrieved from an
+   * injector using {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.
+   */
+  Key<? extends T> getLinkedKey();
+
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/MembersInjectorLookup.java b/core/src/com/google/inject/spi/MembersInjectorLookup.java
new file mode 100644
index 0000000..d4da8bd
--- /dev/null
+++ b/core/src/com/google/inject/spi/MembersInjectorLookup.java
@@ -0,0 +1,103 @@
+/**
+ * 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 com.google.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.inject.Binder;
+import com.google.inject.MembersInjector;
+import com.google.inject.TypeLiteral;
+
+/**
+ * A lookup of the members injector for a type. Lookups are created explicitly in a module using
+ * {@link com.google.inject.Binder#getMembersInjector(Class) getMembersInjector()} statements:
+ * <pre>
+ *     MembersInjector&lt;PaymentService&gt; membersInjector
+ *         = getMembersInjector(PaymentService.class);</pre>
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @since 2.0
+ */
+public final class MembersInjectorLookup<T> implements Element {
+
+  private final Object source;
+  private final TypeLiteral<T> type;
+  private MembersInjector<T> delegate;
+
+  public MembersInjectorLookup(Object source, TypeLiteral<T> type) {
+    this.source = checkNotNull(source, "source");
+    this.type = checkNotNull(type, "type");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  /**
+   * Gets the type containing the members to be injected.
+   */
+  public TypeLiteral<T> getType() {
+    return type;
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  /**
+   * Sets the actual members injector.
+   *
+   * @throws IllegalStateException if the delegate is already set
+   */
+  public void initializeDelegate(MembersInjector<T> delegate) {
+    checkState(this.delegate == null, "delegate already initialized");
+    this.delegate = checkNotNull(delegate, "delegate");
+  }
+
+  public void applyTo(Binder binder) {
+    initializeDelegate(binder.withSource(getSource()).getMembersInjector(type));
+  }
+
+  /**
+   * Returns the delegate members injector, or {@code null} if it has not yet been initialized.
+   * The delegate will be initialized when this element is processed, or otherwise used to create
+   * an injector.
+   */
+  public MembersInjector<T> getDelegate() {
+    return delegate;
+  }
+
+  /**
+   * Returns the looked up members injector. The result is not valid until this lookup has been
+   * initialized, which usually happens when the injector is created. The members injector will
+   * throw an {@code IllegalStateException} if you try to use it beforehand.
+   */
+  public MembersInjector<T> getMembersInjector() {
+    return new MembersInjector<T>() {
+      public void injectMembers(T instance) {
+        checkState(delegate != null,
+            "This MembersInjector cannot be used until the Injector has been created.");
+        delegate.injectMembers(instance);
+      }
+
+      @Override public String toString() {
+        return "MembersInjector<" + type + ">";
+      }
+    };
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/Message.java b/core/src/com/google/inject/spi/Message.java
new file mode 100644
index 0000000..59c4072
--- /dev/null
+++ b/core/src/com/google/inject/spi/Message.java
@@ -0,0 +1,140 @@
+/**
+ * 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 com.google.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Binder;
+import com.google.inject.internal.Errors;
+import com.google.inject.internal.util.SourceProvider;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * An error message and the context in which it occured. Messages are usually created internally by
+ * Guice and its extensions. Messages can be created explicitly in a module using {@link
+ * com.google.inject.Binder#addError(Throwable) addError()} statements:
+ * <pre>
+ *     try {
+ *       bindPropertiesFromFile();
+ *     } catch (IOException e) {
+ *       addError(e);
+ *     }</pre>
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public final class Message implements Serializable, Element {
+  private final String message;
+  private final Throwable cause;
+  private final List<Object> sources;
+
+  /**
+   * @since 2.0
+   */
+  public Message(List<Object> sources, String message, Throwable cause) {
+    this.sources = ImmutableList.copyOf(sources);
+    this.message = checkNotNull(message, "message");
+    this.cause = cause;
+  }
+
+  /**
+   * @since 4.0
+   */
+  public Message(String message, Throwable cause) {
+    this(ImmutableList.of(), message, cause);
+  }
+
+  public Message(Object source, String message) {
+    this(ImmutableList.of(source), message, null);
+  }
+
+  public Message(String message) {
+    this(ImmutableList.of(), message, null);
+  }
+
+  public String getSource() {
+    return sources.isEmpty()
+        ? SourceProvider.UNKNOWN_SOURCE.toString()
+        : Errors.convert(sources.get(sources.size() - 1)).toString();
+  }
+
+  /** @since 2.0 */
+  public List<Object> getSources() {
+    return sources;
+  }
+
+  /**
+   * Gets the error message text.
+   */
+  public String getMessage() {
+    return message;
+  }
+
+  /** @since 2.0 */
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  /**
+   * Returns the throwable that caused this message, or {@code null} if this
+   * message was not caused by a throwable.
+   *
+   * @since 2.0
+   */
+  public Throwable getCause() {
+    return cause;
+  }
+
+  @Override public String toString() {
+    return message;
+  }
+
+  @Override public int hashCode() {
+    return message.hashCode();
+  }
+
+  @Override public boolean equals(Object o) {
+    if (!(o instanceof Message)) {
+      return false;
+    }
+    Message e = (Message) o;
+    return message.equals(e.message) && Objects.equal(cause, e.cause) && sources.equals(e.sources);
+  }
+
+  /** @since 2.0 */
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).addError(this);
+  }
+
+  /**
+   * When serialized, we eagerly convert sources to strings. This hurts our formatting, but it
+   * guarantees that the receiving end will be able to read the message.
+   */
+  private Object writeReplace() throws ObjectStreamException {
+    Object[] sourcesAsStrings = sources.toArray();
+    for (int i = 0; i < sourcesAsStrings.length; i++) {
+      sourcesAsStrings[i] = Errors.convert(sourcesAsStrings[i]).toString();
+    }
+    return new Message(ImmutableList.copyOf(sourcesAsStrings), message, cause);
+  }
+
+  private static final long serialVersionUID = 0;
+}
diff --git a/core/src/com/google/inject/spi/ModuleAnnotatedMethodScanner.java b/core/src/com/google/inject/spi/ModuleAnnotatedMethodScanner.java
new file mode 100644
index 0000000..3c90825
--- /dev/null
+++ b/core/src/com/google/inject/spi/ModuleAnnotatedMethodScanner.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 2015 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.inject.spi;
+
+import com.google.inject.Binder;
+import com.google.inject.Key;
+
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+/**
+ * Allows extensions to scan modules for annotated methods and bind those methods
+ * as providers, similar to {@code @Provides} methods.
+ *
+ * @since 4.0
+ */
+public abstract class ModuleAnnotatedMethodScanner {
+
+  /**
+   * Returns the annotations this should scan for. Every method in the module that has one of these
+   * annotations will create a Provider binding, with the return value of the binding being what's
+   * provided and the parameters of the method being dependencies of the provider.
+   */
+  public abstract Set<? extends Class<? extends Annotation>> annotationClasses();
+
+  /**
+   * Prepares a method for binding. This {@code key} parameter is the key discovered from looking at
+   * the binding annotation and return value of the method. Implementations can modify the key to
+   * instead bind to another key. For example, Multibinder may want to change
+   * {@code @SetProvides String provideFoo()} to bind into a unique Key within the multibinder
+   * instead of binding {@code String}.
+   *
+   * <p>The injection point and annotation are provided in case the implementation wants to set the
+   * key based on the property of the annotation or if any additional preparation is needed for any
+   * of the dependencies. The annotation is guaranteed to be an instance of one the classes returned
+   * by {@link #annotationClasses}.
+   */
+  public abstract <T> Key<T> prepareMethod(Binder binder, Annotation annotation, Key<T> key,
+      InjectionPoint injectionPoint);
+
+}
diff --git a/core/src/com/google/inject/spi/ModuleAnnotatedMethodScannerBinding.java b/core/src/com/google/inject/spi/ModuleAnnotatedMethodScannerBinding.java
new file mode 100644
index 0000000..d632420
--- /dev/null
+++ b/core/src/com/google/inject/spi/ModuleAnnotatedMethodScannerBinding.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2015 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+import com.google.inject.internal.Errors;
+
+/**
+ * Represents a call to {@link Binder#scanModulesForAnnotatedMethods} in a module.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+public final class ModuleAnnotatedMethodScannerBinding implements Element {
+  private final Object source;
+  private final ModuleAnnotatedMethodScanner scanner;
+
+  public ModuleAnnotatedMethodScannerBinding(Object source, ModuleAnnotatedMethodScanner scanner) {
+    this.source = checkNotNull(source, "source");
+    this.scanner = checkNotNull(scanner, "scanner");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public ModuleAnnotatedMethodScanner getScanner() {
+    return scanner;
+  }
+  
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).scanModulesForAnnotatedMethods(scanner);
+  }
+
+  @Override public String toString() {
+    return scanner + " which scans for " + scanner.annotationClasses()
+        + " (bound at " + Errors.convert(source) + ")";
+  }
+}
diff --git a/core/src/com/google/inject/spi/ModuleSource.java b/core/src/com/google/inject/spi/ModuleSource.java
new file mode 100644
index 0000000..1e07de2
--- /dev/null
+++ b/core/src/com/google/inject/spi/ModuleSource.java
@@ -0,0 +1,182 @@
+/**
+ * Copyright (C) 2013 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.inject.spi;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Module;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.internal.util.StackTraceElements.InMemoryStackTraceElement;
+
+import java.util.List;
+
+/**
+ * Associated to a {@link Module module}, provides the module class name, the parent module {@link
+ * ModuleSource source}, and the call stack that ends just before the module {@link
+ * Module#configure(Binder) configure(Binder)} method invocation.
+ */
+final class ModuleSource {
+
+  /**
+   * The class name of module that this {@link ModuleSource} associated to.
+   */
+  private final String moduleClassName;
+
+  /**
+   * The parent {@link ModuleSource module source}.
+   */
+  private final ModuleSource parent;
+
+  /**
+   * The chunk of call stack that starts from the parent module {@link Module#configure(Binder)
+   * configure(Binder)} call and ends just before the module {@link Module#configure(Binder)
+   * configure(Binder)} method invocation. For a module without a parent module the chunk starts
+   * from the bottom of call stack. The array is non-empty if stack trace collection is on.
+   */
+  private final InMemoryStackTraceElement[] partialCallStack;
+
+  /**
+   * Creates a new {@link ModuleSource} with a {@literal null} parent.
+   * @param module the corresponding module
+   * @param partialCallStack the chunk of call stack that starts from the parent module {@link
+   * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link
+   * Module#configure(Binder) configure(Binder)} method invocation
+   */
+  ModuleSource(Object module, StackTraceElement[] partialCallStack) {
+    this(null, module, partialCallStack);
+  }
+
+ /**
+   * Creates a new {@link ModuleSource} Object.
+   * @param parent the parent module {@link ModuleSource source}
+   * @param module the corresponding module
+   * @param partialCallStack the chunk of call stack that starts from the parent module {@link
+   * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link
+   * Module#configure(Binder) configure(Binder)} method invocation
+   */
+  private ModuleSource(
+      /* @Nullable */ ModuleSource parent, Object module, StackTraceElement[] partialCallStack) {
+    Preconditions.checkNotNull(module, "module cannot be null.");
+    Preconditions.checkNotNull(partialCallStack, "partialCallStack cannot be null.");
+    this.parent = parent;
+    this.moduleClassName = module.getClass().getName();
+    this.partialCallStack = StackTraceElements.convertToInMemoryStackTraceElement(partialCallStack);
+  }
+
+  /**
+   * Returns the corresponding module class name.
+   *
+   * @see Class#getName()
+   */
+  String getModuleClassName() {
+    return moduleClassName;
+  }
+
+  /**
+   * Returns the chunk of call stack that starts from the parent module {@link
+   * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link
+   * Module#configure(Binder) configure(Binder)} method invocation. The return array is non-empty
+   * only if stack trace collection is on.
+   */
+  StackTraceElement[] getPartialCallStack() {
+    return StackTraceElements.convertToStackTraceElement(partialCallStack);
+  }
+
+  /**
+   * Returns the size of partial call stack if stack trace collection is on otherwise zero.
+   */
+  int getPartialCallStackSize() {
+    return partialCallStack.length;
+  }
+
+  /**
+   * Creates and returns a child {@link ModuleSource} corresponding to the {@link Module module}.
+   * @param module the corresponding module
+   * @param partialCallStack the chunk of call stack that starts from the parent module {@link
+   * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link
+   * Module#configure(Binder) configure(Binder)} method invocation
+   */
+  ModuleSource createChild(Object module, StackTraceElement[] partialCallStack) {
+    return new ModuleSource(this, module, partialCallStack);
+  }
+
+  /**
+   * Returns the parent module {@link ModuleSource source}.
+   */
+  ModuleSource getParent() {
+    return parent;
+  }
+
+  /**
+   * Returns the class names of modules in this module source. The first element (index 0) is filled
+   * by this object {@link #getModuleClassName()}. The second element is filled by the parent's
+   * {@link #getModuleClassName()} and so on.
+   */
+  List<String> getModuleClassNames() {
+    ImmutableList.Builder<String> classNames = ImmutableList.builder();
+    ModuleSource current = this;
+    while (current != null) {
+      String className = current.moduleClassName;
+      classNames.add(className);
+      current = current.parent;
+    }
+    return classNames.build();
+  }
+
+  /**
+   * Returns the size of {@link ModuleSource ModuleSources} chain (all parents) that ends at this
+   * object.
+   */
+  int size() {
+    if (parent == null) {
+      return 1;
+    }
+    return parent.size() + 1;
+  }
+
+  /**
+   * Returns the size of call stack that ends just before the module {@link Module#configure(Binder)
+   * configure(Binder)} method invocation (see {@link #getStackTrace()}).
+   */
+  int getStackTraceSize() {
+    if (parent == null) {
+      return partialCallStack.length;
+    }
+    return parent.getStackTraceSize() + partialCallStack.length;
+  }
+
+  /**
+   * Returns the full call stack that ends just before the module {@link Module#configure(Binder)
+   * configure(Binder)} method invocation. The return array is non-empty if stack trace collection
+   * on.
+   */
+  StackTraceElement[] getStackTrace() {
+    int stackTraceSize = getStackTraceSize();
+    StackTraceElement[] callStack = new StackTraceElement[stackTraceSize];
+    int cursor = 0;
+    ModuleSource current = this;
+    while (current != null) {
+      StackTraceElement[] chunk =
+          StackTraceElements.convertToStackTraceElement(current.partialCallStack);
+      int chunkSize = chunk.length;
+      System.arraycopy(chunk, 0, callStack, cursor, chunkSize);
+      current = current.parent;
+      cursor = cursor + chunkSize;
+    }
+    return callStack;
+  }
+}
diff --git a/core/src/com/google/inject/spi/PrivateElements.java b/core/src/com/google/inject/spi/PrivateElements.java
new file mode 100644
index 0000000..fc36305
--- /dev/null
+++ b/core/src/com/google/inject/spi/PrivateElements.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Injector;
+import com.google.inject.Key;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A private collection of elements that are hidden from the enclosing injector or module by
+ * default. See {@link com.google.inject.PrivateModule PrivateModule} for details.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface PrivateElements extends Element {
+
+  /**
+   * Returns the configuration information in this private environment.
+   */
+  List<Element> getElements();
+
+  /**
+   * Returns the child injector that hosts these private elements, or null if the elements haven't
+   * been used to create an injector.
+   */
+  Injector getInjector();
+
+  /**
+   * Returns the unique exposed keys for these private elements.
+   */
+  Set<Key<?>> getExposedKeys();
+
+  /**
+   * Returns an arbitrary object containing information about the "place" where this key was
+   * exposed. Used by Guice in the production of descriptive error messages.
+   *
+   * <p>Tools might specially handle types they know about; {@code StackTraceElement} is a good
+   * example. Tools should simply call {@code toString()} on the source object if the type is
+   * unfamiliar.
+   *
+   * @param key one of the keys exposed by this module.
+   */
+  Object getExposedSource(Key<?> key);
+}
diff --git a/core/src/com/google/inject/spi/ProviderBinding.java b/core/src/com/google/inject/spi/ProviderBinding.java
new file mode 100644
index 0000000..caec274
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProviderBinding.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+
+/**
+ * A binding to a {@link Provider} that delegates to the binding for the provided type. This binding
+ * is used whenever a {@code Provider<T>} is injected (as opposed to injecting {@code T} directly).
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface ProviderBinding<T extends Provider<?>> extends Binding<T> {
+
+  /**
+   * Returns the key whose binding is used to {@link Provider#get provide instances}. That binding
+   * can be retrieved from an injector using {@link com.google.inject.Injector#getBinding(Key)
+   * Injector.getBinding(providedKey)}
+   */
+  Key<?> getProvidedKey();
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/ProviderInstanceBinding.java b/core/src/com/google/inject/spi/ProviderInstanceBinding.java
new file mode 100644
index 0000000..99cd9db
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProviderInstanceBinding.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Provider;
+
+import java.util.Set;
+
+/**
+ * A binding to a provider instance. The provider's {@code get} method is invoked to resolve
+ * injections.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface ProviderInstanceBinding<T> extends Binding<T>, HasDependencies {
+
+  /**
+   * If the user supplied a JSR330 binding, then this will wrap that one. To always return the
+   * user-supplied provider, use {@link #getUserSuppliedProvider}.
+   * 
+   * @deprecated Use {@link #getUserSuppliedProvider} instead.
+   */
+  @Deprecated
+  Provider<? extends T> getProviderInstance();
+  
+  /**
+   * Returns the user-supplied, unscoped provider.
+   * @since 4.0
+   */
+  javax.inject.Provider<? extends T> getUserSuppliedProvider();
+
+  /**
+   * Returns the field and method injection points of the provider, injected at injector-creation
+   * time only.
+   *
+   * @return a possibly empty set
+   */
+  Set<InjectionPoint> getInjectionPoints();
+
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/ProviderKeyBinding.java b/core/src/com/google/inject/spi/ProviderKeyBinding.java
new file mode 100644
index 0000000..4a6cfdc
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProviderKeyBinding.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Key;
+
+/**
+ * A binding to a provider key. To resolve injections, the provider key is first resolved, then that
+ * provider's {@code get} method is invoked.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface ProviderKeyBinding<T> extends Binding<T> {
+
+  /**
+   * Returns the key used to resolve the provider's binding. That binding can be retrieved from an
+   * injector using {@link com.google.inject.Injector#getBinding(Key)
+   * Injector.getBinding(providerKey)}
+   */
+  Key<? extends javax.inject.Provider<? extends T>> getProviderKey();
+
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/spi/ProviderLookup.java b/core/src/com/google/inject/spi/ProviderLookup.java
new file mode 100644
index 0000000..3cc2d05
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProviderLookup.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.util.Types;
+
+import java.util.Set;
+
+/**
+ * A lookup of the provider for a type. Lookups are created explicitly in a module using
+ * {@link com.google.inject.Binder#getProvider(Class) getProvider()} statements:
+ * <pre>
+ *     Provider&lt;PaymentService&gt; paymentServiceProvider
+ *         = getProvider(PaymentService.class);</pre>
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class ProviderLookup<T> implements Element {
+  private final Object source;
+  private final Dependency<T> dependency;
+  private Provider<T> delegate;
+
+  public ProviderLookup(Object source, Key<T> key) {
+    this(source, Dependency.get(checkNotNull(key, "key")));
+  }
+
+  /** @since 4.0 */
+  public ProviderLookup(Object source, Dependency<T> dependency) {
+    this.source = checkNotNull(source, "source");
+    this.dependency = checkNotNull(dependency, "dependency");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public Key<T> getKey() {
+    return dependency.getKey();
+  }
+
+  /** @since 4.0 */
+  public Dependency<T> getDependency() {
+    return dependency;
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  /**
+   * Sets the actual provider.
+   *
+   * @throws IllegalStateException if the delegate is already set
+   */
+  public void initializeDelegate(Provider<T> delegate) {
+    checkState(this.delegate == null, "delegate already initialized");
+    this.delegate = checkNotNull(delegate, "delegate");
+  }
+
+  public void applyTo(Binder binder) {
+    initializeDelegate(binder.withSource(getSource()).getProvider(dependency));
+  }
+
+  /**
+   * Returns the delegate provider, or {@code null} if it has not yet been initialized. The delegate
+   * will be initialized when this element is processed, or otherwise used to create an injector.
+   */
+  public Provider<T> getDelegate() {
+    return delegate;
+  }
+
+  /**
+   * Returns the looked up provider. The result is not valid until this lookup has been initialized,
+   * which usually happens when the injector is created. The provider will throw an {@code
+   * IllegalStateException} if you try to use it beforehand.
+   */
+  public Provider<T> getProvider() {
+    return new ProviderWithDependencies<T>() {
+      public T get() {
+        checkState(delegate != null,
+            "This Provider cannot be used until the Injector has been created.");
+        return delegate.get();
+      }
+
+      public Set<Dependency<?>> getDependencies() {
+        // We depend on Provider<T>, not T directly.  This is an important distinction
+        // for dependency analysis tools that short-circuit on providers.
+        Key<?> providerKey = getKey().ofType(Types.providerOf(getKey().getTypeLiteral().getType()));
+        return ImmutableSet.<Dependency<?>>of(Dependency.get(providerKey));
+      }
+
+      @Override public String toString() {
+        return "Provider<" + getKey().getTypeLiteral() + ">";
+      }
+    };
+  }
+}
diff --git a/core/src/com/google/inject/spi/ProviderWithDependencies.java b/core/src/com/google/inject/spi/ProviderWithDependencies.java
new file mode 100644
index 0000000..be87379
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProviderWithDependencies.java
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Provider;
+
+/**
+ * A provider with dependencies on other injected types. If a {@link Provider} has dependencies that
+ * aren't specified in injections, this interface should be used to expose all dependencies.
+ *
+ * @since 2.0
+ */
+public interface ProviderWithDependencies<T> extends Provider<T>, HasDependencies {}
diff --git a/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java b/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java
new file mode 100644
index 0000000..b835b71
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2010 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.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Provider;
+
+/**
+ * A Provider that is part of an extension which supports a custom
+ * BindingTargetVisitor.
+ * <p> 
+ * When an extension binds a provider instance, the provider can implement this
+ * interface to allow users using the
+ * {@link Binding#acceptTargetVisitor(BindingTargetVisitor)} method to visit a
+ * custom visitor designed for that extension. A typical implementation within
+ * the extension would look like
+ * <pre> 
+ * &lt;V, B> V acceptExtensionVisitor(BindingTargetVisitor&lt;B, V> visitor, ProviderInstanceBinding&lt;? extends B> binding) {
+ *   if(visitor instanceof MyCustomExtensionVisitor) {
+ *     return ((MyCustomExtensionVisitor&lt;B, V>)visitor).visitCustomExtension(customProperties, binding);
+ *   } else {
+ *     return visitor.visit(binding);
+ *   }
+ * }</pre> 
+ * 'MyCustomExtensionVisitor' in the example above would be an interface the
+ * extension provides that users can implement in order to be notified of custom
+ * extension information. These visitor interfaces must extend from
+ * BindingTargetVisitor.
+ *
+ * @since 3.0
+ * @author sameb@google.com (Sam Berlin)
+ */
+public interface ProviderWithExtensionVisitor<T> extends Provider<T> {
+
+  /**
+   * Instructs the extension determine if the visitor is an instance of a custom
+   * extension visitor, and if so, visit it using that method. If the visitor is
+   * not an instance of the custom extension visitor, this method <b>MUST</b>
+   * call visitor.visit(binding).
+   * <p> 
+   * Due to issues with generics, the type parameters of this method do not
+   * relate to the type of the provider. In practice, the 'B' type will always
+   * be a supertype of 'T'.
+   */
+  <B, V> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor,
+      ProviderInstanceBinding<? extends B> binding);
+}
diff --git a/core/src/com/google/inject/spi/ProvidesMethodBinding.java b/core/src/com/google/inject/spi/ProvidesMethodBinding.java
new file mode 100644
index 0000000..a862fcc
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProvidesMethodBinding.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2014 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.inject.spi;
+
+import com.google.inject.Key;
+import com.google.inject.Provides;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * An {@literal @}{@link Provides} binding or binding produced by a
+ * {@link ModuleAnnotatedMethodScanner}.
+ *
+ * @since 4.0
+ * @author sameb@google.com (Sam Berlin)
+ */
+public interface ProvidesMethodBinding<T> extends HasDependencies {
+  
+  /** Returns the method this binding uses. */
+  Method getMethod(); 
+  
+  /** Returns the instance of the object the method is defined in. */
+  Object getEnclosingInstance();
+  
+  /** Returns the key of the binding. */
+  Key<T> getKey();
+
+  /**
+   * Returns the annotation that caused this binding to be created. For {@code @Provides} methods,
+   * this is an instance of the {@code @Provides} annotation. For bindings from
+   * {@link ModuleAnnotatedMethodScanner}, this is the annotation that caused the scanner to produce
+   * the binding.
+   */
+  Annotation getAnnotation();
+}
diff --git a/core/src/com/google/inject/spi/ProvidesMethodTargetVisitor.java b/core/src/com/google/inject/spi/ProvidesMethodTargetVisitor.java
new file mode 100644
index 0000000..62c8721
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProvidesMethodTargetVisitor.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2014 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.inject.spi;
+
+import com.google.inject.Provides;
+import com.google.inject.spi.BindingTargetVisitor;
+
+/**
+ * A visitor for the {@literal @}{@link Provides} bindings.
+ * <p>
+ * If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ * {@code @Provides} will be visited through this interface.
+ *
+ * @since 4.0
+ * @author sameb@google.com (Sam Berlin)
+ */
+public interface ProvidesMethodTargetVisitor<T, V> extends BindingTargetVisitor<T, V> {
+  
+  /**
+   * Visits an {@link ProvidesMethodBinding} created with an {@literal @}{@link Provides} method.
+   */
+  V visit(ProvidesMethodBinding<? extends T> providesMethodBinding);
+}
diff --git a/core/src/com/google/inject/spi/ProvisionListener.java b/core/src/com/google/inject/spi/ProvisionListener.java
new file mode 100644
index 0000000..274b8c3
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProvisionListener.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+
+import java.util.List;
+
+/**
+ * Listens for provisioning of objects. Useful for gathering timing information
+ * about provisioning, post-provision initialization, and more.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+public interface ProvisionListener {
+
+  /**
+   * Invoked by Guice when an object requires provisioning. Provisioning occurs
+   * when Guice locates and injects the dependencies for a binding. For types
+   * bound to a Provider, provisioning encapsulates the {@link Provider#get}
+   * method. For toInstance or constant bindings, provisioning encapsulates
+   * the injecting of {@literal @}{@code Inject}ed fields or methods.
+   * For other types, provisioning encapsulates the construction of the
+   * object. If a type is bound within a {@link Scope}, provisioning depends on
+   * the scope. Types bound in Singleton scope will only be provisioned once.
+   * Types bound in no scope will be provisioned every time they are injected.
+   * Other scopes define their own behavior for provisioning.
+   * <p>
+   * To perform the provision, call {@link ProvisionInvocation#provision()}.
+   * If you do not explicitly call provision, it will be automatically done after
+   * this method returns.  It is an error to call provision more than once.
+   */
+  <T> void onProvision(ProvisionInvocation<T> provision);
+
+  /**
+   * Encapsulates a single act of provisioning.
+   *
+   * @since 4.0
+   */ 
+  public abstract static class ProvisionInvocation<T> {
+
+    /**
+     * Returns the Binding this is provisioning.
+     * <p>
+     * You must not call {@link Provider#get()} on the provider returned by
+     * {@link Binding#getProvider}, otherwise you will get confusing error messages.
+     */
+    public abstract Binding<T> getBinding();
+
+    /** Performs the provision, returning the object provisioned. */
+    public abstract T provision();
+    
+    /** Returns the dependency chain that led to this object being provisioned. */
+    public abstract List<DependencyAndSource> getDependencyChain();
+    
+  }
+}
diff --git a/core/src/com/google/inject/spi/ProvisionListenerBinding.java b/core/src/com/google/inject/spi/ProvisionListenerBinding.java
new file mode 100644
index 0000000..4f349d4
--- /dev/null
+++ b/core/src/com/google/inject/spi/ProvisionListenerBinding.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.spi;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.matcher.Matcher;
+
+import java.util.List;
+
+/**
+ * Binds keys (picked using a Matcher) to a provision listener. Listeners are created explicitly in
+ * a module using {@link Binder#bindListener(Matcher, ProvisionListener...)} statements:
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+public final class ProvisionListenerBinding implements Element {
+
+  private final Object source;
+  private final Matcher<? super Binding<?>> bindingMatcher;
+  private final List<ProvisionListener> listeners;
+
+  ProvisionListenerBinding(Object source,
+      Matcher<? super Binding<?>> bindingMatcher,
+      ProvisionListener[] listeners) {
+    this.source = source;
+    this.bindingMatcher = bindingMatcher;
+    this.listeners = ImmutableList.copyOf(listeners);
+  }
+
+  /** Returns the registered listeners. */
+  public List<ProvisionListener> getListeners() {
+    return listeners;
+  }
+
+  /**
+   * Returns the binding matcher which chooses which bindings the listener should be notified of.
+   */  
+  public Matcher<? super Binding<?>> getBindingMatcher() {
+    return bindingMatcher;
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public <R> R acceptVisitor(ElementVisitor<R> visitor) {
+    return visitor.visit(this);
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).bindListener(bindingMatcher,
+        listeners.toArray(new ProvisionListener[listeners.size()]));
+  }
+}
diff --git a/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java b/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
new file mode 100644
index 0000000..03d8c34
--- /dev/null
+++ b/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2012 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+import com.google.inject.Inject;
+
+/**
+ * A request to require explicit {@literal @}{@link Inject} annotations on constructors.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+public final class RequireAtInjectOnConstructorsOption implements Element {
+  private final Object source;
+
+  RequireAtInjectOnConstructorsOption(Object source) {
+    this.source = checkNotNull(source, "source");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).requireAtInjectOnConstructors();
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+}
diff --git a/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java b/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
new file mode 100644
index 0000000..ee52cfc
--- /dev/null
+++ b/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2010 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+
+/**
+ * A request to require exact binding annotations.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+public final class RequireExactBindingAnnotationsOption implements Element {
+  private final Object source;
+
+  RequireExactBindingAnnotationsOption(Object source) {
+    this.source = checkNotNull(source, "source");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).requireExactBindingAnnotations();
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+}
diff --git a/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java b/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
new file mode 100644
index 0000000..5962eb7
--- /dev/null
+++ b/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2010 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+
+/**
+ * A request to require explicit bindings.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 3.0
+ */
+public final class RequireExplicitBindingsOption implements Element {
+  private final Object source;
+
+  RequireExplicitBindingsOption(Object source) {
+    this.source = checkNotNull(source, "source");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).requireExplicitBindings();
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+}
diff --git a/core/src/com/google/inject/spi/ScopeBinding.java b/core/src/com/google/inject/spi/ScopeBinding.java
new file mode 100644
index 0000000..86ed685
--- /dev/null
+++ b/core/src/com/google/inject/spi/ScopeBinding.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+import com.google.inject.Scope;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Registration of a scope annotation with the scope that implements it. Instances are created
+ * explicitly in a module using {@link com.google.inject.Binder#bindScope(Class, Scope) bindScope()}
+ * statements:
+ * <pre>
+ *     Scope recordScope = new RecordScope();
+ *     bindScope(RecordScoped.class, new RecordScope());</pre>
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class ScopeBinding implements Element {
+  private final Object source;
+  private final Class<? extends Annotation> annotationType;
+  private final Scope scope;
+
+  ScopeBinding(Object source, Class<? extends Annotation> annotationType, Scope scope) {
+    this.source = checkNotNull(source, "source");
+    this.annotationType = checkNotNull(annotationType, "annotationType");
+    this.scope = checkNotNull(scope, "scope");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public Class<? extends Annotation> getAnnotationType() {
+    return annotationType;
+  }
+
+  public Scope getScope() {
+    return scope;
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).bindScope(annotationType, scope);
+  }
+}
diff --git a/core/src/com/google/inject/spi/StaticInjectionRequest.java b/core/src/com/google/inject/spi/StaticInjectionRequest.java
new file mode 100644
index 0000000..87e5376
--- /dev/null
+++ b/core/src/com/google/inject/spi/StaticInjectionRequest.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+import com.google.inject.ConfigurationException;
+
+import java.util.Set;
+
+/**
+ * A request to inject the static fields and methods of a type. Requests are created
+ * explicitly in a module using {@link com.google.inject.Binder#requestStaticInjection(Class[])
+ * requestStaticInjection()} statements:
+ * <pre>
+ *     requestStaticInjection(MyLegacyService.class);</pre>
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class StaticInjectionRequest implements Element {
+  private final Object source;
+  private final Class<?> type;
+
+  StaticInjectionRequest(Object source, Class<?> type) {
+    this.source = checkNotNull(source, "source");
+    this.type = checkNotNull(type, "type");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public Class<?> getType() {
+    return type;
+  }
+
+  /**
+   * Returns the static methods and fields of {@code type} that will be injected to fulfill this
+   * request.
+   *
+   * @return a possibly empty set of injection points. The set has a specified iteration order. All
+   *      fields are returned and then all methods. Within the fields, supertype fields are returned
+   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+   *      a field with multiple binding annotations. The exception's {@link
+   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+   *      of the valid injection points.
+   */
+  public Set<InjectionPoint> getInjectionPoints() throws ConfigurationException {
+    return InjectionPoint.forStaticMethodsAndFields(type);
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).requestStaticInjection(type);
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+}
diff --git a/core/src/com/google/inject/spi/Toolable.java b/core/src/com/google/inject/spi/Toolable.java
new file mode 100644
index 0000000..ffabd9d
--- /dev/null
+++ b/core/src/com/google/inject/spi/Toolable.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2010 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.inject.spi;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Instructs an {@link Injector} running in {@link Stage#TOOL} that a method should be injected.
+ * This is typically useful for for extensions to Guice that perform additional validation in an
+ * injected method or field.  This only applies to objects that are already constructed when
+ * bindings are created (ie., something bound using {@link
+ * com.google.inject.binder.LinkedBindingBuilder#toProvider toProvider}, {@link
+ * com.google.inject.binder.LinkedBindingBuilder#toInstance toInstance}, or {@link
+ * com.google.inject.Binder#requestInjection requestInjection}.
+ * 
+ * @author sberlin@gmail.com (Sam Berlin)
+ * @since 3.0
+ */
+@Target({ METHOD })
+@Retention(RUNTIME)
+@Documented
+public @interface Toolable {
+}
diff --git a/core/src/com/google/inject/spi/TypeConverter.java b/core/src/com/google/inject/spi/TypeConverter.java
new file mode 100644
index 0000000..6dd07a3
--- /dev/null
+++ b/core/src/com/google/inject/spi/TypeConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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 com.google.inject.spi;
+
+import com.google.inject.TypeLiteral;
+
+/**
+ * Converts constant string values to a different type.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @since 2.0
+ */
+public interface TypeConverter {
+
+  /**
+   * Converts a string value. Throws an exception if a conversion error occurs.
+   */
+  Object convert(String value, TypeLiteral<?> toType);
+}
diff --git a/core/src/com/google/inject/spi/TypeConverterBinding.java b/core/src/com/google/inject/spi/TypeConverterBinding.java
new file mode 100644
index 0000000..4478627
--- /dev/null
+++ b/core/src/com/google/inject/spi/TypeConverterBinding.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.Errors;
+import com.google.inject.matcher.Matcher;
+
+/**
+ * Registration of type converters for matching target types. Instances are created
+ * explicitly in a module using {@link com.google.inject.Binder#convertToTypes(Matcher,
+ * TypeConverter) convertToTypes()} statements:
+ * <pre>
+ *     convertToTypes(Matchers.only(TypeLiteral.get(DateTime.class)), new DateTimeConverter());</pre>
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class TypeConverterBinding implements Element {
+  private final Object source;
+  private final Matcher<? super TypeLiteral<?>> typeMatcher;
+  private final TypeConverter typeConverter;
+
+  /** @since 3.0 */
+  public TypeConverterBinding(Object source, Matcher<? super TypeLiteral<?>> typeMatcher,
+      TypeConverter typeConverter) {
+    this.source = checkNotNull(source, "source");
+    this.typeMatcher = checkNotNull(typeMatcher, "typeMatcher");
+    this.typeConverter = checkNotNull(typeConverter, "typeConverter");
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public Matcher<? super TypeLiteral<?>> getTypeMatcher() {
+    return typeMatcher;
+  }
+
+  public TypeConverter getTypeConverter() {
+    return typeConverter;
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).convertToTypes(typeMatcher, typeConverter);
+  }
+
+  @Override public String toString() {
+    return typeConverter + " which matches " + typeMatcher
+        + " (bound at " + Errors.convert(source) + ")";
+  }
+}
diff --git a/core/src/com/google/inject/spi/TypeEncounter.java b/core/src/com/google/inject/spi/TypeEncounter.java
new file mode 100644
index 0000000..2ed0ee7
--- /dev/null
+++ b/core/src/com/google/inject/spi/TypeEncounter.java
@@ -0,0 +1,122 @@
+/**
+ * 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 com.google.inject.spi;
+
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.matcher.Matcher;
+
+import java.lang.reflect.Method;
+
+/**
+ * Context of an injectable type encounter. Enables reporting errors, registering injection
+ * listeners and binding method interceptors for injectable type {@code I}. It is an error to use
+ * an encounter after the {@link TypeListener#hear(TypeLiteral, TypeEncounter) hear()} method has
+ * returned.
+ *
+ * @param <I> the injectable type encountered
+ * @since 2.0
+ */
+public interface TypeEncounter<I> {
+
+  /**
+   * Records an error message for type {@code I} which will be presented to the user at a later
+   * time. Unlike throwing an exception, this enable us to continue configuring the Injector and
+   * discover more errors. Uses {@link String#format(String, Object[])} to insert the arguments
+   * into the message.
+   */
+  void addError(String message, Object... arguments);
+
+  /**
+   * Records an exception for type {@code I}, the full details of which will be logged, and the
+   * message of which will be presented to the user at a later time. If your type listener calls
+   * something that you worry may fail, you should catch the exception and pass it to this method.
+   */
+  void addError(Throwable t);
+
+  /**
+   * Records an error message to be presented to the user at a later time.
+   */
+  void addError(Message message);
+
+  /**
+   * Returns the provider used to obtain instances for the given injection key. The returned
+   * provider will not be valid until the injector has been created. The provider will throw an
+   * {@code IllegalStateException} if you try to use it beforehand.
+   */
+  <T> Provider<T> getProvider(Key<T> key);
+
+  /**
+   * Returns the provider used to obtain instances for the given injection type. The returned
+   * provider will not be valid until the injector has been created. The provider will throw an
+   * {@code IllegalStateException} if you try to use it beforehand.
+   */
+  <T> Provider<T> getProvider(Class<T> type);
+
+  /**
+   * Returns the members injector used to inject dependencies into methods and fields on instances
+   * of the given type {@code T}. The returned members injector will not be valid until the main
+   * injector has been created. The members injector will throw an {@code IllegalStateException}
+   * if you try to use it beforehand.
+   *
+   * @param typeLiteral type to get members injector for
+   */
+  <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral);
+
+  /**
+   * Returns the members injector used to inject dependencies into methods and fields on instances
+   * of the given type {@code T}. The returned members injector will not be valid until the main
+   * injector has been created. The members injector will throw an {@code IllegalStateException}
+   * if you try to use it beforehand.
+   *
+   * @param type type to get members injector for
+   */
+  <T> MembersInjector<T> getMembersInjector(Class<T> type);
+
+  /**
+   * Registers a members injector for type {@code I}. Guice will use the members injector after its
+   * performed its own injections on an instance of {@code I}.
+   */
+  void register(MembersInjector<? super I> membersInjector);
+
+  /**
+   * Registers an injection listener for type {@code I}. Guice will notify the listener after all
+   * injections have been performed on an instance of {@code I}.
+   */
+  void register(InjectionListener<? super I> listener);
+
+  /*if[AOP]*/
+  /**
+   * Binds method interceptor[s] to methods matched in type {@code I} and its supertypes. A
+   * method is eligible for interception if:
+   *
+   * <ul>
+   *  <li>Guice created the instance the method is on</li>
+   *  <li>Neither the enclosing type nor the method is final</li>
+   *  <li>And the method is package-private or more accessible</li>
+   * </ul>
+   *
+   * @param methodMatcher matches methods the interceptor should apply to. For
+   *     example: {@code annotatedWith(Transactional.class)}.
+   * @param interceptors to bind
+   */
+  void bindInterceptor(Matcher<? super Method> methodMatcher,
+      org.aopalliance.intercept.MethodInterceptor... interceptors);
+  /*end[AOP]*/
+}
diff --git a/core/src/com/google/inject/spi/TypeListener.java b/core/src/com/google/inject/spi/TypeListener.java
new file mode 100644
index 0000000..ed9d8d3
--- /dev/null
+++ b/core/src/com/google/inject/spi/TypeListener.java
@@ -0,0 +1,48 @@
+/**
+ * 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 com.google.inject.spi;
+
+import com.google.inject.TypeLiteral;
+
+/**
+ * Listens for Guice to encounter injectable types. If a given type has its constructor injected in
+ * one situation but only its methods and fields injected in another, Guice will notify this
+ * listener once.
+ *
+ * <p>Useful for extra type checking, {@linkplain TypeEncounter#register(InjectionListener)
+ * registering injection listeners}, and {@linkplain TypeEncounter#bindInterceptor(
+ * com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])
+ * binding method interceptors}.
+ * 
+ * @since 2.0
+ */
+public interface TypeListener {
+
+  /**
+   * Invoked when Guice encounters a new type eligible for constructor or members injection.
+   * Called during injector creation (or afterwords if Guice encounters a type at run time and
+   * creates a JIT binding).
+   *
+   * @param type encountered by Guice
+   * @param encounter context of this encounter, enables reporting errors, registering injection
+   *     listeners and binding method interceptors for {@code type}.
+   *
+   * @param <I> the injectable type
+   */
+  <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter);
+
+}
diff --git a/core/src/com/google/inject/spi/TypeListenerBinding.java b/core/src/com/google/inject/spi/TypeListenerBinding.java
new file mode 100644
index 0000000..8ad4672
--- /dev/null
+++ b/core/src/com/google/inject/spi/TypeListenerBinding.java
@@ -0,0 +1,67 @@
+/**
+ * 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 com.google.inject.spi;
+
+import com.google.inject.Binder;
+import com.google.inject.TypeLiteral;
+import com.google.inject.matcher.Matcher;
+
+/**
+ * Binds types (picked using a Matcher) to an type listener. Registrations are created explicitly in
+ * a module using {@link com.google.inject.Binder#bindListener(Matcher, TypeListener)} statements:
+ *
+ * <pre>
+ *     register(only(new TypeLiteral&lt;PaymentService&lt;CreditCard>>() {}), listener);</pre>
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class TypeListenerBinding implements Element {
+
+  private final Object source;
+  private final Matcher<? super TypeLiteral<?>> typeMatcher;
+  private final TypeListener listener;
+
+  TypeListenerBinding(Object source, TypeListener listener,
+      Matcher<? super TypeLiteral<?>> typeMatcher) {
+    this.source = source;
+    this.listener = listener;
+    this.typeMatcher = typeMatcher;
+  }
+
+  /** Returns the registered listener. */
+  public TypeListener getListener() {
+    return listener;
+  }
+
+  /** Returns the type matcher which chooses which types the listener should be notified of. */
+  public Matcher<? super TypeLiteral<?>> getTypeMatcher() {
+    return typeMatcher;
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {
+    return visitor.visit(this);
+  }
+
+  public void applyTo(Binder binder) {
+    binder.withSource(getSource()).bindListener(typeMatcher, listener);
+  }
+}
diff --git a/core/src/com/google/inject/spi/UntargettedBinding.java b/core/src/com/google/inject/spi/UntargettedBinding.java
new file mode 100644
index 0000000..4f6f823
--- /dev/null
+++ b/core/src/com/google/inject/spi/UntargettedBinding.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+
+/**
+ * An untargetted binding. This binding indicates that the injector should use its implicit binding
+ * strategies to resolve injections.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public interface UntargettedBinding<T> extends Binding<T> {}
diff --git a/core/src/com/google/inject/spi/package-info.java b/core/src/com/google/inject/spi/package-info.java
new file mode 100644
index 0000000..1224837
--- /dev/null
+++ b/core/src/com/google/inject/spi/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Guice service provider interface
+ */
+package com.google.inject.spi;
diff --git a/core/src/com/google/inject/util/Modules.java b/core/src/com/google/inject/util/Modules.java
new file mode 100644
index 0000000..08ec92c
--- /dev/null
+++ b/core/src/com/google/inject/util/Modules.java
@@ -0,0 +1,359 @@
+/**
+ * Copyright (C) 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.inject.util;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.PrivateBinder;
+import com.google.inject.PrivateModule;
+import com.google.inject.Scope;
+import com.google.inject.internal.Errors;
+import com.google.inject.spi.DefaultBindingScopingVisitor;
+import com.google.inject.spi.DefaultElementVisitor;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.ElementVisitor;
+import com.google.inject.spi.Elements;
+import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding;
+import com.google.inject.spi.PrivateElements;
+import com.google.inject.spi.ScopeBinding;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Static utility methods for creating and working with instances of {@link Module}.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 2.0
+ */
+public final class Modules {
+  private Modules() {}
+  
+  public static final Module EMPTY_MODULE = new EmptyModule();
+  private static class EmptyModule implements Module {
+    public void configure(Binder binder) {}
+  }
+
+  /**
+   * Returns a builder that creates a module that overlays override modules over the given
+   * modules. If a key is bound in both sets of modules, only the binding from the override modules
+   * is kept. If a single {@link PrivateModule} is supplied or all elements are from
+   * a single {@link PrivateBinder}, then this will overwrite the private bindings.
+   * Otherwise, private bindings will not be overwritten unless they are exposed. 
+   * This can be used to replace the bindings of a production module with test bindings:
+   * <pre>
+   * Module functionalTestModule
+   *     = Modules.override(new ProductionModule()).with(new TestModule());
+   * </pre>
+   *
+   * <p>Prefer to write smaller modules that can be reused and tested without overrides.
+   *
+   * @param modules the modules whose bindings are open to be overridden
+   */
+  public static OverriddenModuleBuilder override(Module... modules) {
+    return new RealOverriddenModuleBuilder(Arrays.asList(modules));
+  }
+
+  /**
+   * Returns a builder that creates a module that overlays override modules over the given
+   * modules. If a key is bound in both sets of modules, only the binding from the override modules
+   * is kept. If a single {@link PrivateModule} is supplied or all elements are from
+   * a single {@link PrivateBinder}, then this will overwrite the private bindings.
+   * Otherwise, private bindings will not be overwritten unless they are exposed. 
+   * This can be used to replace the bindings of a production module with test bindings:
+   * <pre>
+   * Module functionalTestModule
+   *     = Modules.override(getProductionModules()).with(getTestModules());
+   * </pre>
+   *
+   * <p>Prefer to write smaller modules that can be reused and tested without overrides.
+   *
+   * @param modules the modules whose bindings are open to be overridden
+   */
+  public static OverriddenModuleBuilder override(Iterable<? extends Module> modules) {
+    return new RealOverriddenModuleBuilder(modules);
+  }
+
+  /**
+   * Returns a new module that installs all of {@code modules}.
+   */
+  public static Module combine(Module... modules) {
+    return combine(ImmutableSet.copyOf(modules));
+  }
+
+  /**
+   * Returns a new module that installs all of {@code modules}.
+   */
+  public static Module combine(Iterable<? extends Module> modules) {
+    return new CombinedModule(modules);
+  }
+  
+  private static class CombinedModule implements Module {
+    final Set<Module> modulesSet;
+    
+    CombinedModule(Iterable<? extends Module> modules) {
+      this.modulesSet = ImmutableSet.copyOf(modules);
+    }
+    
+    public void configure(Binder binder) {
+      binder = binder.skipSources(getClass());
+      for (Module module : modulesSet) {
+        binder.install(module);
+      }
+    }
+  }
+
+  /**
+   * See the EDSL example at {@link Modules#override(Module[]) override()}.
+   */
+  public interface OverriddenModuleBuilder {
+
+    /**
+     * See the EDSL example at {@link Modules#override(Module[]) override()}.
+     */
+    Module with(Module... overrides);
+
+    /**
+     * See the EDSL example at {@link Modules#override(Module[]) override()}.
+     */
+    Module with(Iterable<? extends Module> overrides);
+  }
+
+  private static final class RealOverriddenModuleBuilder implements OverriddenModuleBuilder {
+    private final ImmutableSet<Module> baseModules;
+
+    private RealOverriddenModuleBuilder(Iterable<? extends Module> baseModules) {
+      this.baseModules = ImmutableSet.copyOf(baseModules);
+    }
+
+    public Module with(Module... overrides) {
+      return with(Arrays.asList(overrides));
+    }
+
+    public Module with(Iterable<? extends Module> overrides) {
+      return new OverrideModule(overrides, baseModules);
+    }
+  }
+  
+  static class OverrideModule extends AbstractModule {
+    private final ImmutableSet<Module> overrides;
+    private final ImmutableSet<Module> baseModules;
+    
+    OverrideModule(Iterable<? extends Module> overrides, ImmutableSet<Module> baseModules) {
+      this.overrides = ImmutableSet.copyOf(overrides);
+      this.baseModules = baseModules;
+    }
+
+    @Override
+    public void configure() {
+      Binder baseBinder = binder();
+      List<Element> baseElements = Elements.getElements(currentStage(), baseModules);
+
+      // If the sole element was a PrivateElements, we want to override
+      // the private elements within that -- so refocus our elements
+      // and binder.
+      if(baseElements.size() == 1) {
+        Element element = Iterables.getOnlyElement(baseElements);
+        if(element instanceof PrivateElements) {
+          PrivateElements privateElements = (PrivateElements)element;
+          PrivateBinder privateBinder = baseBinder.newPrivateBinder().withSource(privateElements.getSource());
+          for(Key exposed : privateElements.getExposedKeys()) {
+            privateBinder.withSource(privateElements.getExposedSource(exposed)).expose(exposed);
+          }
+          baseBinder = privateBinder;
+          baseElements = privateElements.getElements();
+        }
+      }
+      
+      final Binder binder = baseBinder.skipSources(this.getClass());
+      final LinkedHashSet<Element> elements = new LinkedHashSet<Element>(baseElements);
+      final Module scannersModule = extractScanners(elements);
+      final List<Element> overrideElements = Elements.getElements(currentStage(),
+          ImmutableList.<Module>builder().addAll(overrides).add(scannersModule).build());
+
+      final Set<Key<?>> overriddenKeys = Sets.newHashSet();
+      final Map<Class<? extends Annotation>, ScopeBinding> overridesScopeAnnotations =
+          Maps.newHashMap();
+
+      // execute the overrides module, keeping track of which keys and scopes are bound
+      new ModuleWriter(binder) {
+        @Override public <T> Void visit(Binding<T> binding) {
+          overriddenKeys.add(binding.getKey());
+          return super.visit(binding);
+        }
+
+        @Override public Void visit(ScopeBinding scopeBinding) {
+          overridesScopeAnnotations.put(scopeBinding.getAnnotationType(), scopeBinding);
+          return super.visit(scopeBinding);
+        }
+
+        @Override public Void visit(PrivateElements privateElements) {
+          overriddenKeys.addAll(privateElements.getExposedKeys());
+          return super.visit(privateElements);
+        }
+      }.writeAll(overrideElements);
+
+      // execute the original module, skipping all scopes and overridden keys. We only skip each
+      // overridden binding once so things still blow up if the module binds the same thing
+      // multiple times.
+      final Map<Scope, List<Object>> scopeInstancesInUse = Maps.newHashMap();
+      final List<ScopeBinding> scopeBindings = Lists.newArrayList();
+      new ModuleWriter(binder) {
+        @Override public <T> Void visit(Binding<T> binding) {
+          if (!overriddenKeys.remove(binding.getKey())) {
+            super.visit(binding);
+
+            // Record when a scope instance is used in a binding
+            Scope scope = getScopeInstanceOrNull(binding);
+            if (scope != null) {
+              List<Object> existing = scopeInstancesInUse.get(scope);
+              if (existing == null) {
+                existing = Lists.newArrayList();
+                scopeInstancesInUse.put(scope, existing);
+              }
+              existing.add(binding.getSource());
+            }
+          }
+
+          return null;
+        }
+
+        void rewrite(Binder binder, PrivateElements privateElements, Set<Key<?>> keysToSkip) {
+          PrivateBinder privateBinder = binder.withSource(privateElements.getSource())
+              .newPrivateBinder();
+
+          Set<Key<?>> skippedExposes = Sets.newHashSet();
+
+          for (Key<?> key : privateElements.getExposedKeys()) {
+            if (keysToSkip.remove(key)) {
+              skippedExposes.add(key);
+            } else {
+              privateBinder.withSource(privateElements.getExposedSource(key)).expose(key);
+            }
+          }
+
+          for (Element element : privateElements.getElements()) {
+            if (element instanceof Binding
+                && skippedExposes.remove(((Binding) element).getKey())) {
+              continue;
+            }
+            if (element instanceof PrivateElements) {
+              rewrite(privateBinder, (PrivateElements) element, skippedExposes);
+              continue;
+            }
+            element.applyTo(privateBinder);
+          }
+        }
+
+        @Override public Void visit(PrivateElements privateElements) {
+          rewrite(binder, privateElements, overriddenKeys);
+          return null;
+        }
+
+        @Override public Void visit(ScopeBinding scopeBinding) {
+          scopeBindings.add(scopeBinding);
+          return null;
+        }
+      }.writeAll(elements);
+
+      // execute the scope bindings, skipping scopes that have been overridden. Any scope that
+      // is overridden and in active use will prompt an error
+      new ModuleWriter(binder) {
+        @Override public Void visit(ScopeBinding scopeBinding) {
+          ScopeBinding overideBinding =
+              overridesScopeAnnotations.remove(scopeBinding.getAnnotationType());
+          if (overideBinding == null) {
+            super.visit(scopeBinding);
+          } else {
+            List<Object> usedSources = scopeInstancesInUse.get(scopeBinding.getScope());
+            if (usedSources != null) {
+              StringBuilder sb = new StringBuilder(
+                  "The scope for @%s is bound directly and cannot be overridden.");
+              sb.append("%n     original binding at " + Errors.convert(scopeBinding.getSource()));
+              for (Object usedSource : usedSources) {
+                sb.append("%n     bound directly at " + Errors.convert(usedSource) + "");
+              }
+              binder.withSource(overideBinding.getSource())
+                  .addError(sb.toString(), scopeBinding.getAnnotationType().getSimpleName());
+            }
+          }
+          return null;
+        }
+      }.writeAll(scopeBindings);
+    }
+
+    private Scope getScopeInstanceOrNull(Binding<?> binding) {
+      return binding.acceptScopingVisitor(new DefaultBindingScopingVisitor<Scope>() {
+        @Override public Scope visitScope(Scope scope) {
+          return scope;
+        }
+      });
+    }
+  }
+
+  private static class ModuleWriter extends DefaultElementVisitor<Void> {
+    protected final Binder binder;
+
+    ModuleWriter(Binder binder) {
+      this.binder = binder.skipSources(this.getClass());
+    }
+
+    @Override protected Void visitOther(Element element) {
+      element.applyTo(binder);
+      return null;
+    }
+
+    void writeAll(Iterable<? extends Element> elements) {
+      for (Element element : elements) {
+        element.acceptVisitor(this);
+      }
+    }
+  }
+
+  private static Module extractScanners(Iterable<Element> elements) {
+    final List<ModuleAnnotatedMethodScannerBinding> scanners = Lists.newArrayList();
+    ElementVisitor<Void> visitor = new DefaultElementVisitor<Void>() {
+      @Override public Void visit(ModuleAnnotatedMethodScannerBinding binding) {
+        scanners.add(binding);
+        return null;
+      }
+    };
+    for (Element element : elements) {
+      element.acceptVisitor(visitor);
+    }
+    return new AbstractModule() {
+      @Override protected void configure() {
+        for (ModuleAnnotatedMethodScannerBinding scanner : scanners) {
+          scanner.applyTo(binder());
+        }
+      }
+    };
+  }
+}
diff --git a/core/src/com/google/inject/util/Providers.java b/core/src/com/google/inject/util/Providers.java
new file mode 100644
index 0000000..c18d351
--- /dev/null
+++ b/core/src/com/google/inject/util/Providers.java
@@ -0,0 +1,156 @@
+/*
+ * 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 com.google.inject.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ProviderWithDependencies;
+
+import java.util.Set;
+
+/**
+ * Static utility methods for creating and working with instances of
+ * {@link Provider}.
+ *
+ * @author Kevin Bourrillion (kevinb9n@gmail.com)
+ * @since 2.0
+ */
+public final class Providers {
+
+  private Providers() {}
+
+  /**
+   * Returns a provider which always provides {@code instance}.  This should not
+   * be necessary to use in your application, but is helpful for several types
+   * of unit tests.
+   *
+   * @param instance the instance that should always be provided.  This is also
+   *     permitted to be null, to enable aggressive testing, although in real
+   *     life a Guice-supplied Provider will never return null.
+   */
+  public static <T> Provider<T> of(final T instance) {
+    return new ConstantProvider<T>(instance);
+  }
+
+  private static final class ConstantProvider<T> implements Provider<T> {
+    private final T instance;
+
+    private ConstantProvider(T instance) {
+      this.instance = instance;
+    }
+
+    public T get() {
+      return instance;
+    }
+
+    @Override public String toString() {
+      return "of(" + instance + ")";
+    }
+
+    @Override public boolean equals(Object obj) {
+      return (obj instanceof ConstantProvider)
+          && Objects.equal(instance, ((ConstantProvider<?>) obj).instance);
+    }
+
+    @Override public int hashCode() {
+      return Objects.hashCode(instance);
+    }
+  }
+
+  /**
+   * Returns a Guice-friendly {@code com.google.inject.Provider} for the given
+   * JSR-330 {@code javax.inject.Provider}. The converse method is unnecessary,
+   * since Guice providers directly implement the JSR-330 interface.
+   * 
+   * @since 3.0
+   */
+  public static <T> Provider<T> guicify(javax.inject.Provider<T> provider) {
+    if (provider instanceof Provider) {
+      return (Provider<T>) provider;
+    }
+  
+    final javax.inject.Provider<T> delegate = checkNotNull(provider, "provider");
+    
+    // Ensure that we inject all injection points from the delegate provider.
+    Set<InjectionPoint> injectionPoints =
+        InjectionPoint.forInstanceMethodsAndFields(provider.getClass());
+    if(injectionPoints.isEmpty()) {
+      return new GuicifiedProvider<T>(delegate);
+    } else {
+      Set<Dependency<?>> mutableDeps = Sets.newHashSet();
+      for(InjectionPoint ip : injectionPoints) {
+        mutableDeps.addAll(ip.getDependencies());
+      }
+      final Set<Dependency<?>> dependencies = ImmutableSet.copyOf(mutableDeps);
+      return new GuicifiedProviderWithDependencies<T>(dependencies, delegate);
+    }
+  }
+
+  private static class GuicifiedProvider<T> implements Provider<T> {
+    protected final javax.inject.Provider<T> delegate;
+
+    private GuicifiedProvider(javax.inject.Provider<T> delegate) {
+      this.delegate = delegate;
+    }
+
+    public T get() {
+      return delegate.get();
+    }
+
+    @Override public String toString() {
+      return "guicified(" + delegate + ")";
+    }
+
+    @Override public boolean equals(Object obj) {
+      return (obj instanceof GuicifiedProvider)
+          && Objects.equal(delegate, ((GuicifiedProvider<?>) obj).delegate);
+    }
+
+    @Override public int hashCode() {
+      return Objects.hashCode(delegate);
+    }
+  }
+
+  private static final class GuicifiedProviderWithDependencies<T>
+      extends GuicifiedProvider<T> implements ProviderWithDependencies<T> {
+    private final Set<Dependency<?>> dependencies;
+
+    private GuicifiedProviderWithDependencies(Set<Dependency<?>> dependencies,
+        javax.inject.Provider<T> delegate) {
+      super(delegate);
+      this.dependencies = dependencies;
+    }
+
+    @SuppressWarnings("unused")
+    @Inject
+    void initialize(Injector injector) {
+      injector.injectMembers(delegate);
+    }
+
+    public Set<Dependency<?>> getDependencies() {
+      return dependencies;
+    }
+  }
+}
diff --git a/core/src/com/google/inject/util/Types.java b/core/src/com/google/inject/util/Types.java
new file mode 100644
index 0000000..c3b3a2a
--- /dev/null
+++ b/core/src/com/google/inject/util/Types.java
@@ -0,0 +1,134 @@
+/**
+ * Copyright (C) 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.inject.util;
+
+import com.google.inject.Provider;
+import com.google.inject.internal.MoreTypes;
+import com.google.inject.internal.MoreTypes.GenericArrayTypeImpl;
+import com.google.inject.internal.MoreTypes.ParameterizedTypeImpl;
+import com.google.inject.internal.MoreTypes.WildcardTypeImpl;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Static methods for working with types.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @since 2.0
+ */
+public final class Types {
+  private Types() {}
+
+  /**
+   * Returns a new parameterized type, applying {@code typeArguments} to
+   * {@code rawType}. The returned type does not have an owner type.
+   *
+   * @return a {@link java.io.Serializable serializable} parameterized type.
+   */
+  public static ParameterizedType newParameterizedType(Type rawType, Type... typeArguments) {
+    return newParameterizedTypeWithOwner(null, rawType, typeArguments);
+  }
+
+  /**
+   * Returns a new parameterized type, applying {@code typeArguments} to
+   * {@code rawType} and enclosed by {@code ownerType}.
+   *
+   * @return a {@link java.io.Serializable serializable} parameterized type.
+   */
+  public static ParameterizedType newParameterizedTypeWithOwner(
+      Type ownerType, Type rawType, Type... typeArguments) {
+    return new ParameterizedTypeImpl(ownerType, rawType, typeArguments);
+  }
+
+  /**
+   * Returns an array type whose elements are all instances of
+   * {@code componentType}.
+   *
+   * @return a {@link java.io.Serializable serializable} generic array type.
+   */
+  public static GenericArrayType arrayOf(Type componentType) {
+    return new GenericArrayTypeImpl(componentType);
+  }
+
+  /**
+   * Returns a type that represents an unknown type that extends {@code bound}.
+   * For example, if {@code bound} is {@code CharSequence.class}, this returns
+   * {@code ? extends CharSequence}. If {@code bound} is {@code Object.class},
+   * this returns {@code ?}, which is shorthand for {@code ? extends Object}.
+   */
+  public static WildcardType subtypeOf(Type bound) {
+    return new WildcardTypeImpl(new Type[] { bound }, MoreTypes.EMPTY_TYPE_ARRAY);
+  }
+
+  /**
+   * Returns a type that represents an unknown supertype of {@code bound}. For
+   * example, if {@code bound} is {@code String.class}, this returns {@code ?
+   * super String}.
+   */
+  public static WildcardType supertypeOf(Type bound) {
+    return new WildcardTypeImpl(new Type[] { Object.class }, new Type[] { bound });
+  }
+
+  /**
+   * Returns a type modelling a {@link List} whose elements are of type
+   * {@code elementType}.
+   *
+   * @return a {@link java.io.Serializable serializable} parameterized type.
+   */
+  public static ParameterizedType listOf(Type elementType) {
+    return newParameterizedType(List.class, elementType);
+  }
+
+  /**
+   * Returns a type modelling a {@link Set} whose elements are of type
+   * {@code elementType}.
+   *
+   * @return a {@link java.io.Serializable serializable} parameterized type.
+   */
+  public static ParameterizedType setOf(Type elementType) {
+    return newParameterizedType(Set.class, elementType);
+  }
+
+  /**
+   * Returns a type modelling a {@link Map} whose keys are of type
+   * {@code keyType} and whose values are of type {@code valueType}.
+   *
+   * @return a {@link java.io.Serializable serializable} parameterized type.
+   */
+  public static ParameterizedType mapOf(Type keyType, Type valueType) {
+    return newParameterizedType(Map.class, keyType, valueType);
+  }
+
+  // for other custom collections types, use newParameterizedType()
+
+  /**
+   * Returns a type modelling a {@link Provider} that provides elements of type
+   * {@code elementType}.
+   *
+   * @return a {@link java.io.Serializable serializable} parameterized type.
+   */
+  public static ParameterizedType providerOf(Type providedType) {
+    return newParameterizedType(Provider.class, providedType);
+  }
+}
\ No newline at end of file
diff --git a/core/src/com/google/inject/util/package-info.java b/core/src/com/google/inject/util/package-info.java
new file mode 100644
index 0000000..89c5de2
--- /dev/null
+++ b/core/src/com/google/inject/util/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Helper methods for working with Guice.
+ */
+package com.google.inject.util;
\ No newline at end of file
diff --git a/core/test/com/google/inject/AllTests.java b/core/test/com/google/inject/AllTests.java
new file mode 100644
index 0000000..f700608
--- /dev/null
+++ b/core/test/com/google/inject/AllTests.java
@@ -0,0 +1,159 @@
+/**
+ * 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 com.google.inject;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.internal.MoreTypesTest;
+import com.google.inject.internal.UniqueAnnotationsTest;
+import com.google.inject.internal.WeakKeySetTest;
+import com.google.inject.internal.util.LineNumbersTest;
+import com.google.inject.matcher.MatcherTest;
+import com.google.inject.name.NamedEquivalanceTest;
+import com.google.inject.name.NamesTest;
+import com.google.inject.spi.BindingTargetVisitorTest;
+import com.google.inject.spi.ElementApplyToTest;
+import com.google.inject.spi.ElementSourceTest;
+import com.google.inject.spi.ElementsTest;
+import com.google.inject.spi.HasDependenciesTest;
+import com.google.inject.spi.InjectionPointTest;
+import com.google.inject.spi.InjectorSpiTest;
+import com.google.inject.spi.ModuleAnnotatedMethodScannerTest;
+import com.google.inject.spi.ModuleRewriterTest;
+import com.google.inject.spi.ModuleSourceTest;
+import com.google.inject.spi.ProviderMethodsTest;
+import com.google.inject.spi.SpiBindingsTest;
+import com.google.inject.spi.ToolStageInjectorTest;
+import com.google.inject.util.NoopOverrideTest;
+import com.google.inject.util.OverrideModuleTest;
+import com.google.inject.util.ProvidersTest;
+import com.google.inject.util.TypesTest;
+
+import com.googlecode.guice.GuiceTck;
+import com.googlecode.guice.Jsr330Test;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import java.util.Set;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class AllTests {
+
+  private static final Set<String> SUPPRESSED_TEST_NAMES = ImmutableSet.of(
+      "testUnscopedProviderWorksOutsideOfRequestedScope(" + ScopesTest.class.getName() + ")",
+      "testCannotConvertUnannotatedBindings(" + TypeConversionTest.class.getName() + ")"
+  );
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+
+    suite.addTest(GuiceTck.suite());
+    suite.addTestSuite(BinderTest.class);
+    suite.addTest(BinderTestSuite.suite());
+    suite.addTestSuite(BindingAnnotationTest.class);
+    suite.addTestSuite(BindingOrderTest.class);
+    suite.addTestSuite(BindingTest.class);
+    suite.addTestSuite(BoundInstanceInjectionTest.class);
+    suite.addTestSuite(BoundProviderTest.class);
+    suite.addTestSuite(CircularDependencyTest.class);
+    suite.addTestSuite(DuplicateBindingsTest.class);
+    // ErrorHandlingTest.class is not a testcase
+    suite.addTestSuite(EagerSingletonTest.class);
+    suite.addTestSuite(GenericInjectionTest.class);
+    suite.addTestSuite(ImplicitBindingTest.class);
+    suite.addTestSuite(TypeListenerTest.class);
+    suite.addTestSuite(InjectorTest.class);
+    suite.addTestSuite(JitBindingsTest.class);
+    // IntegrationTest is AOP-only
+    suite.addTestSuite(KeyTest.class);
+    suite.addTestSuite(LoggerInjectionTest.class);
+    // MethodInterceptionTest is AOP-only
+    suite.addTestSuite(MembersInjectorTest.class);
+    suite.addTestSuite(ModulesTest.class);
+    suite.addTestSuite(ModuleTest.class);
+    suite.addTestSuite(ModuleAnnotatedMethodScannerTest.class);
+    suite.addTestSuite(NullableInjectionPointTest.class);
+    suite.addTestSuite(OptionalBindingTest.class);
+    suite.addTestSuite(OverrideModuleTest.class);
+    suite.addTestSuite(ParentInjectorTest.class);
+    suite.addTestSuite(PrivateModuleTest.class);
+    suite.addTestSuite(ProviderInjectionTest.class);
+    suite.addTestSuite(ProvisionExceptionTest.class);
+    suite.addTestSuite(ProvisionListenerTest.class);
+    // ProxyFactoryTest is AOP-only
+    suite.addTestSuite(ReflectionTest.class);
+    suite.addTestSuite(RequestInjectionTest.class);
+    suite.addTestSuite(RequireAtInjectOnConstructorsTest.class);
+    suite.addTestSuite(ScopesTest.class);
+    suite.addTestSuite(SerializationTest.class);
+    suite.addTestSuite(SuperclassTest.class);
+    suite.addTestSuite(TypeConversionTest.class);
+    suite.addTestSuite(TypeLiteralInjectionTest.class);
+    suite.addTestSuite(TypeLiteralTest.class);
+    suite.addTestSuite(TypeLiteralTypeResolutionTest.class);
+    suite.addTestSuite(WeakKeySetTest.class);
+
+    // internal
+    suite.addTestSuite(LineNumbersTest.class);
+    suite.addTestSuite(MoreTypesTest.class);
+    suite.addTestSuite(UniqueAnnotationsTest.class);
+
+    // matcher
+    suite.addTestSuite(MatcherTest.class);
+
+    // names
+    suite.addTestSuite(NamesTest.class);
+    suite.addTestSuite(NamedEquivalanceTest.class);
+
+    // spi
+    suite.addTestSuite(BindingTargetVisitorTest.class);
+    suite.addTestSuite(ElementsTest.class);
+    suite.addTestSuite(ElementApplyToTest.class);
+    suite.addTestSuite(HasDependenciesTest.class);
+    suite.addTestSuite(InjectionPointTest.class);
+    suite.addTestSuite(InjectorSpiTest.class);
+    suite.addTestSuite(ModuleRewriterTest.class);
+    suite.addTestSuite(ProviderMethodsTest.class);
+    suite.addTestSuite(SpiBindingsTest.class);
+    suite.addTestSuite(ToolStageInjectorTest.class);
+    suite.addTestSuite(ModuleSourceTest.class);
+    suite.addTestSuite(ElementSourceTest.class);
+
+    // tools
+    // suite.addTestSuite(JmxTest.class); not a testcase
+
+    // util
+    suite.addTestSuite(NoopOverrideTest.class);
+    suite.addTestSuite(ProvidersTest.class);
+    suite.addTestSuite(TypesTest.class);
+
+    /*if[AOP]*/
+    suite.addTestSuite(com.google.inject.internal.ProxyFactoryTest.class);
+    suite.addTestSuite(IntegrationTest.class);
+    suite.addTestSuite(MethodInterceptionTest.class);
+    suite.addTestSuite(com.googlecode.guice.BytecodeGenTest.class);
+    /*end[AOP]*/
+
+    // googlecode.guice
+    suite.addTestSuite(com.googlecode.guice.OSGiContainerTest.class);
+    suite.addTestSuite(Jsr330Test.class);
+
+    return SuiteUtils.removeSuppressedTests(suite, SUPPRESSED_TEST_NAMES);
+  }
+}
diff --git a/core/test/com/google/inject/Asserts.java b/core/test/com/google/inject/Asserts.java
new file mode 100644
index 0000000..6c63158
--- /dev/null
+++ b/core/test/com/google/inject/Asserts.java
@@ -0,0 +1,204 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.inject.internal.InternalFlags.IncludeStackTraceOption;
+import static com.google.inject.internal.InternalFlags.getIncludeStackTraceOption;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.testing.GcFinalization;
+
+import junit.framework.Assert;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class Asserts {
+  private Asserts() {}
+
+  /**
+   * Returns the String that would appear in an error message for this chain of classes 
+   * as modules.
+   */
+  public static String asModuleChain(Class... classes) {
+    return Joiner.on(" -> ").appendTo(new StringBuilder(" (via modules: "),
+        Iterables.transform(ImmutableList.copyOf(classes), new Function<Class, String>() {
+          @Override
+          public String apply(Class input) {
+            return input.getName();
+          }
+        })).append(")").toString();
+  }
+
+  /**
+   * Returns the source file appears in error messages based on {@link 
+   * #getIncludeStackTraceOption()} value.
+   */
+  public static String getDeclaringSourcePart(Class clazz) {
+    if (getIncludeStackTraceOption() == IncludeStackTraceOption.OFF) {
+      return ".configure(Unknown Source";
+    }
+    return ".configure(" + clazz.getSimpleName() + ".java:";
+  }
+
+  /**
+   * Returns true if {@link #getIncludeStackTraceOption()} returns {@link
+   * IncludeStackTraceOption#OFF}.
+   */
+  public static boolean isIncludeStackTraceOff() {
+    return getIncludeStackTraceOption() == IncludeStackTraceOption.OFF;
+  }
+
+  /**
+   * Returns true if {@link #getIncludeStackTraceOption()} returns {@link
+   * IncludeStackTraceOption#COMPLETE}.
+   */
+  public static boolean isIncludeStackTraceComplete() {
+    return getIncludeStackTraceOption() == IncludeStackTraceOption.COMPLETE;
+  }
+
+  /**
+   * Fails unless {@code expected.equals(actual)}, {@code
+   * actual.equals(expected)} and their hash codes are equal. This is useful
+   * for testing the equals method itself.
+   */
+  public static void assertEqualsBothWays(Object expected, Object actual) {
+    assertNotNull(expected);
+    assertNotNull(actual);
+    assertEquals("expected.equals(actual)", actual, expected);
+    assertEquals("actual.equals(expected)", expected, actual);
+    assertEquals("hashCode", expected.hashCode(), actual.hashCode());
+  }
+
+  /**
+   * Fails unless {@code text} includes all {@code substrings}, in order.
+   */
+  public static void assertContains(String text, String... substrings) {
+    /*if[NO_AOP]
+    // when we strip out bytecode manipulation, we lose the ability to generate some source lines.
+    if (text.contains("(Unknown Source)")) {
+      return;
+    }
+    end[NO_AOP]*/
+
+    int startingFrom = 0;
+    for (String substring : substrings) {
+      int index = text.indexOf(substring, startingFrom);
+      assertTrue(String.format("Expected \"%s\" to contain substring \"%s\"", text, substring),
+          index >= startingFrom);
+      startingFrom = index + substring.length();
+    }
+
+    String lastSubstring = substrings[substrings.length - 1];
+    assertTrue(String.format("Expected \"%s\" to contain substring \"%s\" only once),",
+        text, lastSubstring), text.indexOf(lastSubstring, startingFrom) == -1);
+  }
+
+  /**
+   * Fails unless {@code object} doesn't equal itself when reserialized.
+   */
+  public static void assertEqualWhenReserialized(Object object)
+      throws IOException {
+    Object reserialized = reserialize(object);
+    assertEquals(object, reserialized);
+    assertEquals(object.hashCode(), reserialized.hashCode());
+  }
+
+  /**
+   * Fails unless {@code object} has the same toString value when reserialized.
+   */
+  public static void assertSimilarWhenReserialized(Object object) throws IOException {
+    Object reserialized = reserialize(object);
+    assertEquals(object.toString(), reserialized.toString());
+  }
+
+  public static <E> E reserialize(E original) throws IOException {
+    try {
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      new ObjectOutputStream(out).writeObject(original);
+      ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+      @SuppressWarnings("unchecked") // the reserialized type is assignable
+      E reserialized = (E) new ObjectInputStream(in).readObject();
+      return reserialized;
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public static void assertNotSerializable(Object object) throws IOException {
+    try {
+      reserialize(object);
+      Assert.fail();
+    } catch (NotSerializableException expected) {
+    }
+  }
+
+  public static void awaitFullGc() {
+    // GcFinalization *should* do it, but doesn't work well in practice...
+    // so we put a second latch and wait for a ReferenceQueue to tell us.
+    ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
+    WeakReference ref = new WeakReference<Object>(new Object(), queue);
+    GcFinalization.awaitFullGc();
+    try {
+      assertSame("queue didn't return ref in time", ref, queue.remove(5000));
+    } catch (IllegalArgumentException e) {
+      throw new RuntimeException(e);
+    } catch (InterruptedException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public static void awaitClear(WeakReference<?> ref) {
+    // GcFinalization *should* do it, but doesn't work well in practice...
+    // so we put a second latch and wait for a ReferenceQueue to tell us.
+    Object data = ref.get();
+    ReferenceQueue<Object> queue = null;
+    WeakReference extraRef = null;
+    if (data != null) {
+      queue = new ReferenceQueue<Object>();
+      extraRef = new WeakReference<Object>(data, queue);
+      data = null;
+    }
+    GcFinalization.awaitClear(ref);
+    if (queue != null) {
+      try {
+        assertSame("queue didn't return ref in time", extraRef, queue.remove(5000));
+      } catch (IllegalArgumentException e) {
+        throw new RuntimeException(e);
+      } catch (InterruptedException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+}
diff --git a/core/test/com/google/inject/BinderTest.java b/core/test/com/google/inject/BinderTest.java
new file mode 100644
index 0000000..fb8f2c5
--- /dev/null
+++ b/core/test/com/google/inject/BinderTest.java
@@ -0,0 +1,634 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.asModuleChain;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.assertNotSerializable;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static com.google.inject.Asserts.isIncludeStackTraceOff;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Message;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class BinderTest extends TestCase {
+
+  private final Logger loggerToWatch = Logger.getLogger(Guice.class.getName());
+
+  private final List<LogRecord> logRecords = Lists.newArrayList();
+  private final Handler fakeHandler = new Handler() {
+    @Override
+    public void publish(LogRecord logRecord) {
+      logRecords.add(logRecord);
+    }
+    @Override
+    public void flush() {}
+    @Override
+    public void close() throws SecurityException {}
+  };
+
+  Provider<Foo> fooProvider;
+
+  @Override protected void setUp() throws Exception {
+    super.setUp();
+    loggerToWatch.addHandler(fakeHandler);
+  }
+
+  @Override protected void tearDown() throws Exception {
+    loggerToWatch.removeHandler(fakeHandler);
+    super.tearDown();
+  }
+
+  public void testProviderFromBinder() {
+    Guice.createInjector(new Module() {
+      public void configure(Binder binder) {
+        fooProvider = binder.getProvider(Foo.class);
+
+        try {
+          fooProvider.get();
+        } catch (IllegalStateException e) { /* expected */ }
+      }
+    });
+
+    assertNotNull(fooProvider.get());
+  }
+
+  static class Foo {}
+
+  public void testMissingBindings() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        public void configure() {
+          getProvider(Runnable.class);
+          bind(Comparator.class);
+          requireBinding(Key.get(new TypeLiteral<Callable<String>>() {}));
+          bind(Date.class).annotatedWith(Names.named("date"));
+        }
+      });
+    } catch (CreationException e) {
+      assertEquals(4, e.getErrorMessages().size());
+      String segment1 = "No implementation for " + Comparator.class.getName() + " was bound.";
+      String segment2 = "No implementation for java.util.Date annotated with @"
+          + Named.class.getName() + "(value=date) was bound.";
+      String segment3 = "No implementation for java.lang.Runnable was bound.";
+      String segment4 = " No implementation for java.util.concurrent.Callable<java.lang.String> was"
+          + " bound.";
+      String atSegment = "at " + getClass().getName();
+      String sourceFileName = getDeclaringSourcePart(getClass());
+      if (isIncludeStackTraceOff()) {
+        assertContains(e.getMessage(),
+            segment1, atSegment, sourceFileName,
+            segment2, atSegment, sourceFileName,
+            segment3, atSegment, sourceFileName,
+            segment4, atSegment, sourceFileName);
+      } else {
+        assertContains(e.getMessage(),
+            segment3, atSegment, sourceFileName,
+            segment1, atSegment, sourceFileName,
+            segment4, atSegment, sourceFileName,
+            segment2, atSegment, sourceFileName);
+      }
+    }
+  }
+
+  public void testMissingDependency() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        public void configure() {
+          bind(NeedsRunnable.class);
+        }
+      });
+    } catch (CreationException e) {
+      assertEquals(1, e.getErrorMessages().size());
+      assertContains(e.getMessage(),
+          "No implementation for java.lang.Runnable was bound.",
+          "for field at " + NeedsRunnable.class.getName(), ".runnable(BinderTest.java:",
+          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  static class NeedsRunnable {
+    @Inject Runnable runnable;
+  }
+
+  public void testDanglingConstantBinding() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override public void configure() {
+          bindConstant();
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Missing constant value. Please call to(...).",
+          "at " + getClass().getName());
+    }
+  }
+
+  public void testRecursiveBinding() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override public void configure() {
+          bind(Runnable.class).to(Runnable.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Binding points to itself.",
+          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  public void testBindingNullConstant() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override public void configure() {
+          String none = null;
+          bindConstant().annotatedWith(Names.named("nullOne")).to(none);
+          bind(String.class).annotatedWith(Names.named("nullTwo")).toInstance(none);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Binding to null instances is not allowed. Use toProvider(Providers.of(null))",
+          "2) Binding to null instances is not allowed. Use toProvider(Providers.of(null))");
+    }
+  }
+
+  public void testToStringOnBinderApi() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override public void configure() {
+          assertEquals("Binder", binder().toString());
+          assertEquals("Provider<java.lang.Integer>", getProvider(Integer.class).toString());
+          assertEquals("Provider<java.util.List<java.lang.String>>",
+              getProvider(Key.get(new TypeLiteral<List<String>>() {})).toString());
+
+          assertEquals("BindingBuilder<java.lang.Integer>",
+              bind(Integer.class).toString());
+          assertEquals("BindingBuilder<java.lang.Integer>",
+              bind(Integer.class).annotatedWith(Names.named("a")).toString());
+          assertEquals("ConstantBindingBuilder", bindConstant().toString());
+          assertEquals("ConstantBindingBuilder",
+              bindConstant().annotatedWith(Names.named("b")).toString());
+          assertEquals("AnnotatedElementBuilder",
+              binder().newPrivateBinder().expose(Integer.class).toString());
+        }
+      });
+      fail();
+    } catch (CreationException ignored) {
+    }
+  }
+
+  public void testNothingIsSerializableInBinderApi() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override public void configure() {
+          try {
+            assertNotSerializable(binder());
+            assertNotSerializable(getProvider(Integer.class));
+            assertNotSerializable(getProvider(Key.get(new TypeLiteral<List<String>>() {})));
+            assertNotSerializable(bind(Integer.class));
+            assertNotSerializable(bind(Integer.class).annotatedWith(Names.named("a")));
+            assertNotSerializable(bindConstant());
+            assertNotSerializable(bindConstant().annotatedWith(Names.named("b")));
+          } catch (IOException e) {
+            fail(e.getMessage());
+          }
+        }
+      });
+      fail();
+    } catch (CreationException ignored) {
+    }
+  }
+
+  /**
+   * Although {@code String[].class} isn't equal to {@code new
+   * GenericArrayTypeImpl(String.class)}, Guice should treat these two types
+   * interchangeably.
+   */
+  public void testArrayTypeCanonicalization() {
+    final String[] strings = new String[] { "A" };
+    final Integer[] integers = new Integer[] { 1 };
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String[].class).toInstance(strings);
+        bind(new TypeLiteral<Integer[]>() {}).toInstance(integers);
+      }
+    });
+
+    assertSame(integers, injector.getInstance(Key.get(new TypeLiteral<Integer[]>() {})));
+    assertSame(integers, injector.getInstance(new Key<Integer[]>() {}));
+    assertSame(integers, injector.getInstance(Integer[].class));
+    assertSame(strings, injector.getInstance(Key.get(new TypeLiteral<String[]>() {})));
+    assertSame(strings, injector.getInstance(new Key<String[]>() {}));
+    assertSame(strings, injector.getInstance(String[].class));
+
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(String[].class).toInstance(new String[] { "A" });
+          bind(new TypeLiteral<String[]>() {}).toInstance(new String[] { "B" });
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) A binding to java.lang.String[] was already configured at " + getClass().getName(),
+          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
+      assertContains(expected.getMessage(), "1 error");
+    }
+
+    // passes because duplicates are ignored
+    injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String[].class).toInstance(strings);
+        bind(new TypeLiteral<String[]>() {}).toInstance(strings);
+      }
+    });
+    assertSame(strings, injector.getInstance(Key.get(new TypeLiteral<String[]>() {})));
+    assertSame(strings, injector.getInstance(new Key<String[]>() {}));
+    assertSame(strings, injector.getInstance(String[].class));
+  }
+
+  static class ParentModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new FooModule());
+      install(new BarModule());
+    }
+  }
+  static class FooModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new ConstantModule("foo"));
+    }
+  }
+  static class BarModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new ConstantModule("bar"));
+    }
+  }
+  static class ConstantModule extends AbstractModule {
+    private final String constant;
+    ConstantModule(String constant) {
+      this.constant = constant;
+    }
+    @Override protected void configure() {
+      bind(String.class).toInstance(constant);
+    }
+  }
+
+  /**
+   * Binding something to two different things should give an error.
+   */
+  public void testSettingBindingTwice() {
+    try {
+      Guice.createInjector(new ParentModule());
+      fail();
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(),
+        "1) A binding to java.lang.String was already configured at " + ConstantModule.class.getName(),
+        asModuleChain(ParentModule.class, FooModule.class, ConstantModule.class),
+        "at " + ConstantModule.class.getName(), getDeclaringSourcePart(getClass()),
+        asModuleChain(ParentModule.class, BarModule.class, ConstantModule.class));
+      assertContains(expected.getMessage(), "1 error");
+    }
+  }
+
+  /**
+   * Binding an @ImplementedBy thing to something else should also fail.
+   */
+  public void testSettingAtImplementedByTwice() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(HasImplementedBy1.class);
+          bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
+        }
+      });
+      fail();
+    } catch(CreationException expected) {
+      expected.printStackTrace();
+      assertContains(expected.getMessage(),
+        "1) A binding to " + HasImplementedBy1.class.getName()
+        + " was already configured at " + getClass().getName(),
+        "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
+      assertContains(expected.getMessage(), "1 error");
+    }
+  }
+
+  /**
+   * See issue 614, Problem One
+   * https://github.com/google/guice/issues/614
+   */
+  public void testJitDependencyDoesntBlockOtherExplicitBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(HasImplementedByThatNeedsAnotherImplementedBy.class);
+        bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
+      }
+    });
+    injector.getAllBindings(); // just validate it doesn't throw.
+    // Also validate that we're using the explicit (and not @ImplementedBy) implementation
+    assertFalse(injector.getInstance(HasImplementedBy1.class) instanceof ImplementsHasImplementedBy1);
+  }
+
+  /**
+   * See issue 614, Problem Two
+   * https://github.com/google/guice/issues/id=614
+   */
+  public void testJitDependencyCanUseExplicitDependencies() {
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(HasImplementedByThatWantsExplicit.class);
+        bind(JustAnInterface.class).toInstance(new JustAnInterface() {});
+      }
+    });
+  }
+
+  /**
+   * Untargetted bindings should follow @ImplementedBy and @ProvidedBy
+   * annotations if they exist. Otherwise the class should be constructed
+   * directly.
+   */
+  public void testUntargettedBinding() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(HasProvidedBy1.class);
+        bind(HasImplementedBy1.class);
+        bind(HasProvidedBy2.class);
+        bind(HasImplementedBy2.class);
+        bind(JustAClass.class);
+      }
+    });
+
+    assertNotNull(injector.getInstance(HasProvidedBy1.class));
+    assertNotNull(injector.getInstance(HasImplementedBy1.class));
+    assertNotSame(HasProvidedBy2.class,
+        injector.getInstance(HasProvidedBy2.class).getClass());
+    assertSame(ExtendsHasImplementedBy2.class,
+        injector.getInstance(HasImplementedBy2.class).getClass());
+    assertSame(JustAClass.class, injector.getInstance(JustAClass.class).getClass());
+  }
+
+  public void testPartialInjectorGetInstance() {
+    Injector injector = Guice.createInjector();
+    try {
+      injector.getInstance(MissingParameter.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Could not find a suitable constructor in " + NoInjectConstructor.class.getName(),
+          "at " + MissingParameter.class.getName() + ".<init>(BinderTest.java:");
+    }
+  }
+
+  public void testUserReportedError() {
+    final Message message = new Message(getClass(), "Whoops!");
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          addError(message);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertSame(message, Iterables.getOnlyElement(expected.getErrorMessages()));
+    }
+  }
+
+  public void testUserReportedErrorsAreAlsoLogged() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          addError(new Message("Whoops!", new IllegalArgumentException()));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+    }
+
+    LogRecord logRecord = Iterables.getOnlyElement(this.logRecords);
+    assertContains(logRecord.getMessage(),
+        "An exception was caught and reported. Message: java.lang.IllegalArgumentException");
+  }
+
+  public void testBindingToProvider() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(new TypeLiteral<Provider<String>>() {}).toInstance(Providers.of("A"));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Binding to Provider is not allowed.",
+          "at " + BinderTest.class.getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  static class OuterCoreModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new InnerCoreModule());
+    }
+  }
+  static class InnerCoreModule extends AbstractModule {
+    final Named red = Names.named("red");
+
+    @Override protected void configure() {
+      bind(AbstractModule.class).annotatedWith(red)
+      .toProvider(Providers.<AbstractModule>of(null));
+      bind(Binder.class).annotatedWith(red).toProvider(Providers.<Binder>of(null));
+      bind(Binding.class).annotatedWith(red).toProvider(Providers.<Binding>of(null));
+      bind(Injector.class).annotatedWith(red).toProvider(Providers.<Injector>of(null));
+      bind(Key.class).annotatedWith(red).toProvider(Providers.<Key>of(null));
+      bind(Module.class).annotatedWith(red).toProvider(Providers.<Module>of(null));
+      bind(Provider.class).annotatedWith(red).toProvider(Providers.<Provider>of(null));
+      bind(Scope.class).annotatedWith(red).toProvider(Providers.<Scope>of(null));
+      bind(Stage.class).annotatedWith(red).toProvider(Providers.<Stage>of(null));
+      bind(TypeLiteral.class).annotatedWith(red).toProvider(Providers.<TypeLiteral>of(null));
+      bind(new TypeLiteral<Key<String>>() {}).toProvider(Providers.<Key<String>>of(null));
+    }
+  }
+  public void testCannotBindToGuiceTypes() {
+    try {
+      Guice.createInjector(new OuterCoreModule());
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Binding to core guice framework type is not allowed: AbstractModule.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: Binder.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: Binding.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: Injector.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: Key.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: Module.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to Provider is not allowed.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: Scope.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: Stage.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: TypeLiteral.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
+
+          "Binding to core guice framework type is not allowed: Key.",
+          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterCoreModule.class, InnerCoreModule.class));
+    }
+  }
+
+  static class MissingParameter {
+    @Inject MissingParameter(NoInjectConstructor noInjectConstructor) {}
+  }
+
+  static class NoInjectConstructor {
+    private NoInjectConstructor() {}
+  }
+
+  @ProvidedBy(HasProvidedBy1Provider.class)
+  interface HasProvidedBy1 {}
+
+  static class HasProvidedBy1Provider implements Provider<HasProvidedBy1> {
+    public HasProvidedBy1 get() {
+      return new HasProvidedBy1() {};
+    }
+  }
+
+  @ImplementedBy(ImplementsHasImplementedBy1.class)
+  interface HasImplementedBy1 {}
+
+  static class ImplementsHasImplementedBy1 implements HasImplementedBy1 {}
+
+  @ProvidedBy(HasProvidedBy2Provider.class)
+  static class HasProvidedBy2 {}
+
+  static class HasProvidedBy2Provider implements Provider<HasProvidedBy2> {
+    public HasProvidedBy2 get() {
+      return new HasProvidedBy2() {};
+    }
+  }
+
+  @ImplementedBy(ExtendsHasImplementedBy2.class)
+  static class HasImplementedBy2 {}
+
+  static class ExtendsHasImplementedBy2 extends HasImplementedBy2 {}
+
+  static class JustAClass {}
+
+  @ImplementedBy(ImplementsHasImplementedByThatNeedsAnotherImplementedBy.class)
+  static interface HasImplementedByThatNeedsAnotherImplementedBy {
+  }
+
+  static class ImplementsHasImplementedByThatNeedsAnotherImplementedBy
+    implements HasImplementedByThatNeedsAnotherImplementedBy {
+    @Inject
+    ImplementsHasImplementedByThatNeedsAnotherImplementedBy(
+        HasImplementedBy1 h1n1) {}
+  }
+
+  @ImplementedBy(ImplementsHasImplementedByThatWantsExplicit.class)
+  static interface HasImplementedByThatWantsExplicit {
+  }
+
+  static class ImplementsHasImplementedByThatWantsExplicit
+      implements HasImplementedByThatWantsExplicit {
+    @Inject ImplementsHasImplementedByThatWantsExplicit(JustAnInterface jai) {}
+  }
+
+  static interface JustAnInterface {}
+
+
+//  public void testBindInterfaceWithoutImplementation() {
+//    Guice.createInjector(new AbstractModule() {
+//      protected void configure() {
+//        bind(Runnable.class);
+//      }
+//    }).getInstance(Runnable.class);
+//  }
+
+  enum Roshambo { ROCK, SCISSORS, PAPER }
+
+  public void testInjectRawProvider() {
+    try {
+      Guice.createInjector().getInstance(Provider.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      Asserts.assertContains(expected.getMessage(),
+          "1) Cannot inject a Provider that has no type parameter",
+          "while locating " + Provider.class.getName());
+    }
+  }
+}
diff --git a/core/test/com/google/inject/BinderTestSuite.java b/core/test/com/google/inject/BinderTestSuite.java
new file mode 100644
index 0000000..b34cfe0
--- /dev/null
+++ b/core/test/com/google/inject/BinderTestSuite.java
@@ -0,0 +1,769 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.name.Names.named;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.ScopedBindingBuilder;
+import com.google.inject.name.Named;
+import com.google.inject.util.Providers;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class BinderTestSuite extends TestCase {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+
+    new Builder()
+        .name("bind A")
+        .module(new AbstractModule() {
+          protected void configure() {
+            bind(A.class);
+          }
+        })
+        .creationException("No implementation for %s was bound", A.class.getName())
+        .addToSuite(suite);
+
+    new Builder()
+        .name("bind PlainA named apple")
+        .module(new AbstractModule() {
+          protected void configure() {
+            bind(PlainA.class).annotatedWith(named("apple"));
+          }
+        })
+        .creationException("No implementation for %s annotated with %s was bound",
+            PlainA.class.getName(), named("apple"))
+        .addToSuite(suite);
+
+    new Builder()
+        .name("bind A to new PlainA(1)")
+        .module(new AbstractModule() {
+          protected void configure() {
+            bind(A.class).toInstance(new PlainA(1));
+          }
+        })
+        .creationTime(CreationTime.NONE)
+        .expectedValues(new PlainA(1), new PlainA(1), new PlainA(1))
+        .addToSuite(suite);
+
+    new Builder()
+        .name("no binding, AWithProvidedBy")
+        .key(Key.get(AWithProvidedBy.class), InjectsAWithProvidedBy.class)
+        .addToSuite(suite);
+
+    new Builder()
+        .name("no binding, AWithImplementedBy")
+        .key(Key.get(AWithImplementedBy.class), InjectsAWithImplementedBy.class)
+        .addToSuite(suite);
+
+    new Builder()
+        .name("no binding, ScopedA")
+        .key(Key.get(ScopedA.class), InjectsScopedA.class)
+        .expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202))
+        .addToSuite(suite);
+
+    new Builder()
+        .name("no binding, AWithProvidedBy named apple")
+        .key(Key.get(AWithProvidedBy.class, named("apple")),
+            InjectsAWithProvidedByNamedApple.class)
+        .configurationException("No implementation for %s annotated with %s was bound",
+            AWithProvidedBy.class.getName(), named("apple"))
+        .addToSuite(suite);
+
+    new Builder()
+        .name("no binding, AWithImplementedBy named apple")
+        .key(Key.get(AWithImplementedBy.class, named("apple")),
+            InjectsAWithImplementedByNamedApple.class)
+        .configurationException("No implementation for %s annotated with %s was bound",
+            AWithImplementedBy.class.getName(), named("apple"))
+        .addToSuite(suite);
+
+    new Builder()
+        .name("no binding, ScopedA named apple")
+        .key(Key.get(ScopedA.class, named("apple")), InjectsScopedANamedApple.class)
+        .configurationException("No implementation for %s annotated with %s was bound",
+            ScopedA.class.getName(), named("apple"))
+        .addToSuite(suite);
+
+    for (final Scoper scoper : Scoper.values()) {
+      new Builder()
+          .name("bind PlainA")
+          .key(Key.get(PlainA.class), InjectsPlainA.class)
+          .module(new AbstractModule() {
+            protected void configure() {
+              AnnotatedBindingBuilder<PlainA> abb = bind(PlainA.class);
+              scoper.configure(abb);
+            }
+          })
+          .scoper(scoper)
+          .addToSuite(suite);
+
+      new Builder()
+          .name("bind A to PlainA")
+          .module(new AbstractModule() {
+            protected void configure() {
+              ScopedBindingBuilder sbb = bind(A.class).to(PlainA.class);
+              scoper.configure(sbb);
+            }
+          })
+          .scoper(scoper)
+          .addToSuite(suite);
+
+      new Builder()
+          .name("bind A to PlainAProvider.class")
+          .module(new AbstractModule() {
+            protected void configure() {
+              ScopedBindingBuilder sbb = bind(A.class).toProvider(PlainAProvider.class);
+              scoper.configure(sbb);
+            }
+          })
+          .scoper(scoper)
+          .addToSuite(suite);
+
+      new Builder()
+          .name("bind A to new PlainAProvider()")
+          .module(new AbstractModule() {
+            protected void configure() {
+              ScopedBindingBuilder sbb = bind(A.class).toProvider(new PlainAProvider());
+              scoper.configure(sbb);
+            }
+          })
+          .scoper(scoper)
+          .addToSuite(suite);
+
+      new Builder()
+          .name("bind AWithProvidedBy")
+          .key(Key.get(AWithProvidedBy.class), InjectsAWithProvidedBy.class)
+          .module(new AbstractModule() {
+            protected void configure() {
+              ScopedBindingBuilder sbb = bind(AWithProvidedBy.class);
+              scoper.configure(sbb);
+            }
+          })
+          .scoper(scoper)
+          .addToSuite(suite);
+
+      new Builder()
+          .name("bind AWithImplementedBy")
+          .key(Key.get(AWithImplementedBy.class), InjectsAWithImplementedBy.class)
+          .module(new AbstractModule() {
+            protected void configure() {
+              ScopedBindingBuilder sbb = bind(AWithImplementedBy.class);
+              scoper.configure(sbb);
+            }
+          })
+          .scoper(scoper)
+          .addToSuite(suite);
+
+      new Builder()
+          .name("bind ScopedA")
+          .key(Key.get(ScopedA.class), InjectsScopedA.class)
+          .module(new AbstractModule() {
+            protected void configure() {
+              ScopedBindingBuilder sbb = bind(ScopedA.class);
+              scoper.configure(sbb);
+            }
+          })
+          .expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202))
+          .scoper(scoper)
+          .addToSuite(suite);
+
+
+      new Builder()
+          .name("bind AWithProvidedBy named apple")
+          .module(new AbstractModule() {
+            protected void configure() {
+              scoper.configure(bind(AWithProvidedBy.class).annotatedWith(named("apple")));
+            }
+          })
+          .creationException("No implementation for %s annotated with %s was bound",
+              AWithProvidedBy.class.getName(), named("apple"))
+          .addToSuite(suite);
+
+      new Builder()
+          .name("bind AWithImplementedBy named apple")
+          .module(new AbstractModule() {
+            protected void configure() {
+              scoper.configure(bind(AWithImplementedBy.class).annotatedWith(named("apple")));
+            }
+          })
+          .creationException("No implementation for %s annotated with %s was bound",
+              AWithImplementedBy.class.getName(), named("apple"))
+          .addToSuite(suite);
+
+      new Builder()
+          .name("bind ScopedA named apple")
+          .module(new AbstractModule() {
+            protected void configure() {
+              scoper.configure(bind(ScopedA.class).annotatedWith(named("apple")));
+            }
+          })
+          .creationException("No implementation for %s annotated with %s was bound",
+              ScopedA.class.getName(), named("apple"))
+          .addToSuite(suite);
+
+    }
+    
+    return suite;
+  }
+  
+  enum Scoper {
+    UNSCOPED {
+      void configure(ScopedBindingBuilder sbb) {}
+      void apply(Builder builder) {}
+    },
+
+    EAGER_SINGLETON {
+      void configure(ScopedBindingBuilder sbb) {
+        sbb.asEagerSingleton();
+      }
+      void apply(Builder builder) {
+        builder.expectedValues(new PlainA(101), new PlainA(101), new PlainA(101));
+        builder.creationTime(CreationTime.EAGER);
+      }
+    },
+
+    SCOPES_SINGLETON {
+      void configure(ScopedBindingBuilder sbb) {
+        sbb.in(Scopes.SINGLETON);
+      }
+      void apply(Builder builder) {
+        builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(201));
+      }
+    },
+
+    SINGLETON_DOT_CLASS {
+      void configure(ScopedBindingBuilder sbb) {
+        sbb.in(Singleton.class);
+      }
+      void apply(Builder builder) {
+        builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(201));
+      }
+    },
+
+    TWO_AT_A_TIME_SCOPED_DOT_CLASS {
+      void configure(ScopedBindingBuilder sbb) {
+        sbb.in(TwoAtATimeScoped.class);
+      }
+      void apply(Builder builder) {
+        builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202));
+      }
+    },
+
+    TWO_AT_A_TIME_SCOPE {
+      void configure(ScopedBindingBuilder sbb) {
+        sbb.in(new TwoAtATimeScope());
+      }
+      void apply(Builder builder) {
+        builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202));
+      }
+    };
+
+    abstract void configure(ScopedBindingBuilder sbb);
+    abstract void apply(Builder builder);
+  }
+
+  /** When Guice creates a value, directly or via a provider */
+  enum CreationTime {
+    NONE, EAGER, LAZY
+  }
+
+  public static class Builder {
+    private String name = "test";
+    private Key<?> key = Key.get(A.class);
+    private Class<? extends Injectable> injectsKey = InjectsA.class;
+    private List<Module> modules = Lists.<Module>newArrayList(new AbstractModule() {
+      protected void configure() {
+        bindScope(TwoAtATimeScoped.class, new TwoAtATimeScope());
+      }
+    });
+    private List<Object> expectedValues = Lists.<Object>newArrayList(
+        new PlainA(201), new PlainA(202), new PlainA(203));
+    private CreationTime creationTime = CreationTime.LAZY;
+    private String creationException;
+    private String configurationException;
+
+    public Builder module(Module module) {
+      this.modules.add(module);
+      return this;
+    }
+
+    public Builder creationTime(CreationTime creationTime) {
+      this.creationTime = creationTime;
+      return this;
+    }
+
+    public Builder name(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public Builder key(Key<?> key, Class<? extends Injectable> injectsKey) {
+      this.key = key;
+      this.injectsKey = injectsKey;
+      return this;
+    }
+
+    private Builder creationException(String message, Object... args) {
+      this.creationException = String.format(message, args);
+      return this;
+    }
+
+    private Builder configurationException(String message, Object... args) {
+      configurationException = String.format(message, args);
+      return this;
+    }
+
+    private Builder scoper(Scoper scoper) {
+      name(name + " in " + scoper);
+      scoper.apply(this);
+      return this;
+    }
+
+    private <T> Builder expectedValues(T... values) {
+      this.expectedValues.clear();
+      Collections.addAll(this.expectedValues, values);
+      return this;
+    }
+
+    public void addToSuite(TestSuite suite) {
+      if (creationException != null) {
+        suite.addTest(new CreationExceptionTest(this));
+
+      } else if (configurationException != null) {
+        suite.addTest(new ConfigurationExceptionTest(this));
+
+      } else {
+        suite.addTest(new SuccessTest(this));
+        if (creationTime != CreationTime.NONE) {
+          suite.addTest(new UserExceptionsTest(this));
+        }
+      }
+    }
+  }
+
+  public static class SuccessTest extends TestCase {
+    final String name;
+    final Key<?> key;
+    final Class<? extends Injectable> injectsKey;
+    final ImmutableList<Module> modules;
+    final ImmutableList<Object> expectedValues;
+
+    public SuccessTest(Builder builder) {
+      super("test");
+      name = builder.name;
+      key = builder.key;
+      injectsKey = builder.injectsKey;
+      modules = ImmutableList.copyOf(builder.modules);
+      expectedValues = ImmutableList.copyOf(builder.expectedValues);
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    Injector newInjector() {
+      nextId.set(101);
+      return Guice.createInjector(modules);
+    }
+
+    public void test() throws IllegalAccessException, InstantiationException {
+      Injector injector = newInjector();
+      nextId.set(201);
+      for (Object value : expectedValues) {
+        assertEquals(value, injector.getInstance(key));
+      }
+
+      Provider<?> provider = newInjector().getProvider(key);
+      nextId.set(201);
+      for (Object value : expectedValues) {
+        assertEquals(value, provider.get());
+      }
+
+      Provider<?> bindingProvider = newInjector().getBinding(key).getProvider();
+      nextId.set(201);
+      for (Object value : expectedValues) {
+        assertEquals(value, bindingProvider.get());
+      }
+
+      injector = newInjector();
+      nextId.set(201);
+      for (Object value : expectedValues) {
+        Injectable instance = injector.getInstance(injectsKey);
+        assertEquals(value, instance.value);
+      }
+
+      injector = newInjector();
+      nextId.set(201);
+      for (Object value : expectedValues) {
+        Injectable injectable = injectsKey.newInstance();
+        injector.injectMembers(injectable);
+        assertEquals(value, injectable.value);
+      }
+
+      Injector injector1 = newInjector();
+      nextId.set(201);
+      Injectable hasProvider = injector1.getInstance(injectsKey);
+      hasProvider.provider.get();
+      nextId.set(201);
+      for (Object value : expectedValues) {
+        assertEquals(value, hasProvider.provider.get());
+      }
+    }
+  }
+
+  public static class CreationExceptionTest extends TestCase {
+    final String name;
+    final Key<?> key;
+    final ImmutableList<Module> modules;
+    final String creationException;
+
+    public CreationExceptionTest(Builder builder) {
+      super("test");
+      name = builder.name;
+      key = builder.key;
+      modules = ImmutableList.copyOf(builder.modules);
+      creationException = builder.creationException;
+    }
+
+    public String getName() {
+      return "creation errors:" + name;
+    }
+
+    public void test() {
+      try {
+        Guice.createInjector(modules);
+        fail();
+      } catch (CreationException expected) {
+        assertContains(expected.getMessage(), creationException);
+      }
+    }
+  }
+
+  public static class ConfigurationExceptionTest extends TestCase {
+    final String name;
+    final Key<?> key;
+    final Class<? extends Injectable> injectsKey;
+    final ImmutableList<Module> modules;
+    final String configurationException;
+
+    public ConfigurationExceptionTest(Builder builder) {
+      super("test");
+      name = builder.name;
+      key = builder.key;
+      injectsKey = builder.injectsKey;
+      modules = ImmutableList.copyOf(builder.modules);
+      configurationException = builder.configurationException;
+    }
+
+    public String getName() {
+      return "provision errors:" + name;
+    }
+
+    Injector newInjector() {
+      return Guice.createInjector(modules);
+    }
+
+    public void test() throws IllegalAccessException, InstantiationException {
+      try {
+        newInjector().getProvider(key);
+        fail();
+      } catch (ConfigurationException expected) {
+        assertContains(expected.getMessage(), configurationException);
+      }
+
+      try {
+        newInjector().getBinding(key).getProvider();
+        fail();
+      } catch (ConfigurationException expected) {
+        assertContains(expected.getMessage(), configurationException);
+      }
+
+      try {
+        newInjector().getInstance(key);
+        fail();
+      } catch (ConfigurationException expected) {
+        assertContains(expected.getMessage(), configurationException);
+      }
+
+      try {
+        newInjector().getInstance(injectsKey);
+        fail();
+      } catch (ConfigurationException expected) {
+        assertContains(expected.getMessage(),
+            configurationException, injectsKey.getName() + ".inject",
+            configurationException, injectsKey.getName() + ".inject",
+            "2 errors");
+      }
+
+      try {
+        Injectable injectable = injectsKey.newInstance();
+        newInjector().injectMembers(injectable);
+        fail();
+      } catch (ConfigurationException expected) {
+        assertContains(expected.getMessage(),
+            configurationException, injectsKey.getName() + ".inject",
+            configurationException, injectsKey.getName() + ".inject",
+            "2 errors");
+      }
+    }
+  }
+
+  public static class UserExceptionsTest extends TestCase {
+    final String name;
+    final Key<?> key;
+    final Class<? extends Injectable> injectsKey;
+    final ImmutableList<Module> modules;
+    final ImmutableList<Object> expectedValues;
+    final CreationTime creationTime;
+
+    public UserExceptionsTest(Builder builder) {
+      super("test");
+      name = builder.name;
+      key = builder.key;
+      injectsKey = builder.injectsKey;
+      modules = ImmutableList.copyOf(builder.modules);
+      expectedValues = ImmutableList.copyOf(builder.expectedValues);
+      creationTime = builder.creationTime;
+    }
+
+    public String getName() {
+      return "provision errors:" + name;
+    }
+
+    Injector newInjector() {
+      return Guice.createInjector(modules);
+    }
+
+    public void test() throws IllegalAccessException, InstantiationException {
+      nextId.set(-1);
+      try {
+        newInjector();
+        assertEquals(CreationTime.LAZY, creationTime);
+      } catch (CreationException expected) {
+        assertEquals(CreationTime.EAGER, creationTime);
+        assertContains(expected.getMessage(), "Illegal value: -1");
+        return;
+      }
+
+      Provider<?> provider = newInjector().getProvider(key);
+      Provider<?> bindingProvider = newInjector().getBinding(key).getProvider();
+
+      nextId.set(-1);
+      try {
+        newInjector().getInstance(key);
+        fail();
+      } catch (ProvisionException expected) {
+        assertContains(expected.getMessage(), "Illegal value: -1");
+      }
+
+      nextId.set(-1);
+      try {
+        provider.get();
+        fail();
+      } catch (ProvisionException expected) {
+        assertContains(expected.getMessage(), "Illegal value: -1");
+      }
+
+      nextId.set(-1);
+      try {
+        bindingProvider.get();
+        fail();
+      } catch (ProvisionException expected) {
+        assertContains(expected.getMessage(), "Illegal value: -1");
+      }
+
+      try {
+        nextId.set(-1);
+        newInjector().getInstance(injectsKey);
+      } catch (ProvisionException expected) {
+        assertContains(expected.getMessage(), "Illegal value: -1",
+            "for parameter 0 at " + injectsKey.getName() + ".inject");
+      }
+
+      nextId.set(201);
+      Injectable injectable = injectsKey.newInstance();
+      try {
+        nextId.set(-1);
+        newInjector().injectMembers(injectable);
+      } catch (ProvisionException expected) {
+        assertContains(expected.getMessage(), "Illegal value: -1",
+            "for parameter 0 at " + injectsKey.getName() + ".inject");
+      }
+
+      nextId.set(201);
+      Injectable hasProvider = newInjector().getInstance(injectsKey);
+      hasProvider.provider.get();
+      try {
+        nextId.set(-1);
+        hasProvider.provider.get();
+      } catch (ProvisionException expected) {
+        assertContains(expected.getMessage(), "Illegal value: -1");
+      }
+    }
+  }
+
+  /** negative to throw, 101... for eager singletons, 201... for everything else */
+  static final AtomicInteger nextId = new AtomicInteger();
+
+  @ProvidedBy(PlainAProvider.class)
+  interface AWithProvidedBy {}
+
+  static class InjectsAWithProvidedBy extends Injectable {
+    @Inject public void inject(AWithProvidedBy aWithProvidedBy,
+        Provider<AWithProvidedBy> aWithProvidedByProvider) {
+      this.value = aWithProvidedBy;
+      this.provider = aWithProvidedByProvider;
+    }
+  }
+
+  static class InjectsAWithProvidedByNamedApple extends Injectable {
+    @Inject public void inject(@Named("apple") AWithProvidedBy aWithProvidedBy,
+        @Named("apple") Provider<AWithProvidedBy> aWithProvidedByProvider) {
+      this.value = aWithProvidedBy;
+      this.provider = aWithProvidedByProvider;
+    }
+  }
+
+  @ImplementedBy(PlainA.class)
+  interface AWithImplementedBy {}
+
+  static class InjectsAWithImplementedBy extends Injectable {
+    @Inject public void inject(AWithImplementedBy aWithImplementedBy,
+        Provider<AWithImplementedBy> aWithImplementedByProvider) {
+      this.value = aWithImplementedBy;
+      this.provider = aWithImplementedByProvider;
+    }
+  }
+
+  static class InjectsAWithImplementedByNamedApple extends Injectable {
+    @Inject public void inject(@Named("apple") AWithImplementedBy aWithImplementedBy,
+        @Named("apple") Provider<AWithImplementedBy> aWithImplementedByProvider) {
+      this.value = aWithImplementedBy;
+      this.provider = aWithImplementedByProvider;
+    }
+  }
+
+  interface A extends AWithProvidedBy, AWithImplementedBy {}
+
+  static class InjectsA extends Injectable {
+    @Inject public void inject(A a, Provider<A> aProvider) {
+      this.value = a;
+      this.provider = aProvider;
+    }
+  }
+
+  static class PlainA implements A {
+    final int value;
+    PlainA() {
+      value = nextId.getAndIncrement();
+      if (value < 0) {
+        throw new RuntimeException("Illegal value: " + value);
+      }
+    }
+    PlainA(int value) {
+      this.value = value;
+    }
+    public boolean equals(Object obj) {
+      return obj instanceof PlainA
+          && value == ((PlainA) obj).value;
+    }
+    public int hashCode() {
+      return value;
+    }
+    public String toString() {
+      return "PlainA#" + value;
+    }
+  }
+
+  static class PlainAProvider implements Provider<A> {
+    public A get() {
+      return new PlainA();
+    }
+  }
+
+  static class InjectsPlainA extends Injectable {
+    @Inject public void inject(PlainA plainA, Provider<PlainA> plainAProvider) {
+      this.value = plainA;
+      this.provider = plainAProvider;
+    }
+  }
+
+  /** This scope hands out each value exactly twice  */
+  static class TwoAtATimeScope implements Scope {
+    public <T> Provider<T> scope(Key<T> key, final Provider<T> unscoped) {
+      return new Provider<T>() {
+        T instance;
+        public T get() {
+          if (instance == null) {
+            instance = unscoped.get();
+            return instance;
+          } else {
+            T result = instance;
+            instance = null;
+            return result;
+          }
+        }
+      };
+    }
+  }
+
+  @Target({ TYPE, METHOD }) @Retention(RUNTIME) @ScopeAnnotation
+  public @interface TwoAtATimeScoped {}
+
+  @TwoAtATimeScoped
+  static class ScopedA extends PlainA {}
+
+  static class InjectsScopedA extends Injectable {
+    @Inject public void inject(ScopedA scopedA, Provider<ScopedA> scopedAProvider) {
+      this.value = scopedA;
+      this.provider = scopedAProvider;
+    }
+  }
+
+  static class InjectsScopedANamedApple extends Injectable {
+    @Inject public void inject(@Named("apple") ScopedA scopedA,
+        @Named("apple") Provider<ScopedA> scopedAProvider) {
+      this.value = scopedA;
+      this.provider = scopedAProvider;
+    }
+  }
+
+  static class Injectable {
+    Object value = new Object();
+    Provider<?> provider = Providers.of(new Object());
+  }
+}
diff --git a/core/test/com/google/inject/BindingAnnotationTest.java b/core/test/com/google/inject/BindingAnnotationTest.java
new file mode 100644
index 0000000..b119953
--- /dev/null
+++ b/core/test/com/google/inject/BindingAnnotationTest.java
@@ -0,0 +1,169 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class BindingAnnotationTest extends TestCase {
+
+  public void testAnnotationWithValueMatchesKeyWithTypeOnly() throws CreationException {
+    Injector c = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindConstant().annotatedWith(Blue.class).to("foo");
+        bind(BlueFoo.class);
+      }
+    });
+
+    BlueFoo foo = c.getInstance(BlueFoo.class);
+
+    assertEquals("foo", foo.s);
+  }
+
+  public void testRequireExactAnnotationsDisablesFallback() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExactBindingAnnotations();
+          bindConstant().annotatedWith(Blue.class).to("foo");
+          bind(BlueFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
+          "BindingAnnotationTest$Blue(value=5) was bound",
+          "at " + BindingAnnotationTest.class.getName(),
+          getDeclaringSourcePart(getClass()));
+    }
+  }
+  
+  public void testRequireExactAnnotationsDoesntBreakIfDefaultsExist() {
+       Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExactBindingAnnotations();
+          bindConstant().annotatedWith(Red.class).to("foo");
+          bind(RedFoo.class);
+        }
+      }).getInstance(RedFoo.class);      
+  }
+
+  public void testRequireExactAnnotationsRequireAllOptionals() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExactBindingAnnotations();
+          bindConstant().annotatedWith(Color.class).to("foo");
+          bind(ColorFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
+          "BindingAnnotationTest$Color",
+          "at " + BindingAnnotationTest.class.getName(),
+          getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  public void testAnnotationWithValueThatDoesntMatch() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bindConstant().annotatedWith(createBlue(6)).to("six");
+          bind(String.class).toInstance("bar");
+          bind(BlueFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
+          "BindingAnnotationTest$Blue(value=5) was bound",
+          "at " + BindingAnnotationTest.class.getName(),
+          getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  static class BlueFoo {
+    @Inject @Blue(5) String s; 
+  }
+  
+  static class RedFoo {
+    @Inject @Red String s;
+  }
+  
+  static class ColorFoo {
+    @Inject @Color(b=2) String s;
+  }
+
+  @Retention(RUNTIME)
+  @BindingAnnotation
+  @interface Blue {
+    int value();
+  }
+  
+  @Retention(RUNTIME)
+  @BindingAnnotation
+  @interface Red {
+    int r() default 42;
+    int g() default 42;
+    int b() default 42;
+  }
+  
+  @Retention(RUNTIME)
+  @BindingAnnotation
+  @interface Color {
+    int r() default 0;
+    int g() default 0;
+    int b();
+  }
+
+  public Blue createBlue(final int value) {
+    return new Blue() {
+      public int value() {
+        return value;
+      }
+
+      public Class<? extends Annotation> annotationType() {
+        return Blue.class;
+      }
+
+      @Override public boolean equals(Object o) {
+        return o instanceof Blue
+            && ((Blue) o).value() == value;
+      }
+
+      @Override public int hashCode() {
+        return 127 * "value".hashCode() ^ value;
+      }
+    };
+  }
+}
diff --git a/core/test/com/google/inject/BindingOrderTest.java b/core/test/com/google/inject/BindingOrderTest.java
new file mode 100644
index 0000000..6754cad
--- /dev/null
+++ b/core/test/com/google/inject/BindingOrderTest.java
@@ -0,0 +1,99 @@
+/**
+ * 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 com.google.inject;
+
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+
+public class BindingOrderTest extends TestCase {
+
+  public void testBindingOutOfOrder() {
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(BoundFirst.class);
+        bind(BoundSecond.class).to(BoundSecondImpl.class);
+      }
+    });
+  }
+
+  public static class BoundFirst {
+    @Inject public BoundFirst(BoundSecond boundSecond) { }
+  }
+
+  interface BoundSecond { }
+  static class BoundSecondImpl implements BoundSecond { }
+
+  public void testBindingOrderAndScopes() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(A.class);
+        bind(B.class).asEagerSingleton();
+      }
+    });
+
+    assertSame(injector.getInstance(A.class).b, injector.getInstance(A.class).b);
+  }
+
+  public void testBindingWithExtraThreads() throws InterruptedException {
+    final CountDownLatch ready = new CountDownLatch(1);
+    final CountDownLatch done = new CountDownLatch(1);
+    final AtomicReference<B> ref = new AtomicReference<B>();
+
+    final Object createsAThread = new Object() {
+      @Inject void createAnotherThread(final Injector injector) {
+        new Thread() {
+          public void run() {
+            ready.countDown();
+            A a = injector.getInstance(A.class);
+            ref.set(a.b);
+            done.countDown();
+          }
+        }.start();
+
+        // to encourage collisions, we make sure the other thread is running before returning
+        try {
+          ready.await();
+        } catch (InterruptedException e) {
+          throw new RuntimeException(e);
+        }
+      }
+    };
+
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        requestInjection(createsAThread);
+        bind(A.class).toInstance(new A());
+      }
+    });
+
+    done.await();
+    assertNotNull(ref.get());
+  }
+
+  static class A {
+    @Inject B b;
+  }
+
+  static class B { }
+}
diff --git a/core/test/com/google/inject/BindingTest.java b/core/test/com/google/inject/BindingTest.java
new file mode 100644
index 0000000..7da597d
--- /dev/null
+++ b/core/test/com/google/inject/BindingTest.java
@@ -0,0 +1,503 @@
+/*
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.Runnables;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.TypeEncounter;
+import com.google.inject.spi.TypeListener;
+
+import junit.framework.TestCase;
+
+/*if[AOP]*/
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+/*end[AOP]*/
+
+import java.lang.reflect.Constructor;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class BindingTest extends TestCase {
+
+  static class Dependent {
+    @Inject A a;
+    @Inject Dependent(A a, B b) {}
+    @Inject void injectBob(Bob bob) {}
+  }
+
+  public void testExplicitCyclicDependency() {
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(A.class);
+        bind(B.class);
+      }
+    }).getInstance(A.class);
+  }
+
+  static class A { @Inject B b; }
+  static class B { @Inject A a; }
+
+  static class Bob {}
+
+  static class MyModule extends AbstractModule {
+
+    protected void configure() {
+      // Linked.
+      bind(Object.class).to(Runnable.class).in(Scopes.SINGLETON);
+
+      // Instance.
+      bind(Runnable.class).toInstance(Runnables.doNothing());
+
+      // Provider instance.
+      bind(Foo.class).toProvider(new Provider<Foo>() {
+        public Foo get() {
+          return new Foo();
+        }
+      }).in(Scopes.SINGLETON);
+
+      // Provider.
+      bind(Foo.class)
+          .annotatedWith(named("provider"))
+          .toProvider(FooProvider.class);
+
+      // Class.
+      bind(Bar.class).in(Scopes.SINGLETON);
+
+      // Constant.
+      bindConstant().annotatedWith(named("name")).to("Bob");
+    }
+  }
+
+  static class Foo {}
+
+  public static class FooProvider implements Provider<Foo> {
+    public Foo get() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  public static class Bar {}
+
+  public void testBindToUnboundLinkedBinding() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(Collection.class).to(List.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "No implementation for java.util.List was bound.");
+    }
+  }
+
+  /**
+   * This test ensures that the asEagerSingleton() scoping applies to the key,
+   * not to what the key is linked to.
+   */
+  public void testScopeIsAppliedToKeyNotTarget() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Integer.class).toProvider(Counter.class).asEagerSingleton();
+        bind(Number.class).toProvider(Counter.class).asEagerSingleton();
+      }
+    });
+
+    assertNotSame(injector.getInstance(Integer.class), injector.getInstance(Number.class));
+  }
+
+  static class Counter implements Provider<Integer> {
+    static AtomicInteger next = new AtomicInteger(1);
+    public Integer get() {
+      return next.getAndIncrement();
+    }
+  }
+
+  public void testAnnotatedNoArgConstructor() {
+    assertBindingSucceeds(PublicNoArgAnnotated.class);
+    assertBindingSucceeds(ProtectedNoArgAnnotated.class);
+    assertBindingSucceeds(PackagePrivateNoArgAnnotated.class);
+    assertBindingSucceeds(PrivateNoArgAnnotated.class);
+  }
+
+  static class PublicNoArgAnnotated {
+    @Inject public PublicNoArgAnnotated() { }
+  }
+
+  static class ProtectedNoArgAnnotated {
+    @Inject protected ProtectedNoArgAnnotated() { }
+  }
+
+  static class PackagePrivateNoArgAnnotated {
+    @Inject PackagePrivateNoArgAnnotated() { }
+  }
+
+  static class PrivateNoArgAnnotated {
+    @Inject private PrivateNoArgAnnotated() { }
+  }
+
+  public void testUnannotatedNoArgConstructor() throws Exception{
+    assertBindingSucceeds(PublicNoArg.class);
+    assertBindingSucceeds(ProtectedNoArg.class);
+    assertBindingSucceeds(PackagePrivateNoArg.class);
+    assertBindingSucceeds(PrivateNoArgInPrivateClass.class);
+    assertBindingFails(PrivateNoArg.class);
+  }
+
+  static class PublicNoArg {
+    public PublicNoArg() { }
+  }
+
+  static class ProtectedNoArg {
+    protected ProtectedNoArg() { }
+  }
+
+  static class PackagePrivateNoArg {
+    PackagePrivateNoArg() { }
+  }
+
+  private static class PrivateNoArgInPrivateClass {
+    PrivateNoArgInPrivateClass() { }
+  }
+
+  static class PrivateNoArg {
+    private PrivateNoArg() { }
+  }
+
+  private void assertBindingSucceeds(final Class<?> clazz) {
+    assertNotNull(Guice.createInjector().getInstance(clazz));
+  }
+
+  private void assertBindingFails(final Class<?> clazz) throws NoSuchMethodException {
+    try {
+      Guice.createInjector().getInstance(clazz);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "Could not find a suitable constructor in " + PrivateNoArg.class.getName(),
+          "at " + PrivateNoArg.class.getName() + ".class(BindingTest.java:");
+    }
+  }
+
+  public void testTooManyConstructors() {
+    try {
+      Guice.createInjector().getInstance(TooManyConstructors.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          TooManyConstructors.class.getName() + " has more than one constructor annotated with " 
+              + "@Inject. Classes must have either one (and only one) constructor",
+          "at " + TooManyConstructors.class.getName() + ".class(BindingTest.java:");
+    }
+  }
+
+  static class TooManyConstructors {
+    @Inject TooManyConstructors(Injector i) {}
+    @Inject TooManyConstructors() {}
+  }
+
+  public void testToConstructorBinding() throws NoSuchMethodException {
+    final Constructor<D> constructor = D.class.getConstructor(Stage.class);
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Object.class).toConstructor(constructor);
+      }
+    });
+
+    D d = (D) injector.getInstance(Object.class);
+    assertEquals(Stage.DEVELOPMENT, d.stage);
+  }
+
+  public void testToConstructorBindingsOnParameterizedTypes() throws NoSuchMethodException {
+    final Constructor<C> constructor = C.class.getConstructor(Stage.class, Object.class);
+    final Key<Object> s = new Key<Object>(named("s")) {};
+    final Key<Object> i = new Key<Object>(named("i")) {};
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(s).toConstructor(constructor, new TypeLiteral<C<Stage>>() {});
+        bind(i).toConstructor(constructor, new TypeLiteral<C<Injector>>() {});
+      }
+    });
+
+    C<Stage> one = (C<Stage>) injector.getInstance(s);
+    assertEquals(Stage.DEVELOPMENT, one.stage);
+    assertEquals(Stage.DEVELOPMENT, one.t);
+    assertEquals(Stage.DEVELOPMENT, one.anotherT);
+
+    C<Injector> two = (C<Injector>) injector.getInstance(i);
+    assertEquals(Stage.DEVELOPMENT, two.stage);
+    assertEquals(injector, two.t);
+    assertEquals(injector, two.anotherT);
+  }
+
+  public void testToConstructorBindingsFailsOnRawTypes() throws NoSuchMethodException {
+    final Constructor constructor = C.class.getConstructor(Stage.class, Object.class);
+
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(Object.class).toConstructor(constructor);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) T cannot be used as a key; It is not fully specified.",
+          "at " + C.class.getName() + ".<init>(BindingTest.java:",
+          "2) T cannot be used as a key; It is not fully specified.",
+          "at " + C.class.getName() + ".anotherT(BindingTest.java:");
+    }
+  }
+
+/*if[AOP]*/
+  public void testToConstructorAndMethodInterceptors() throws NoSuchMethodException {
+    final Constructor<D> constructor = D.class.getConstructor(Stage.class);
+    final AtomicInteger count = new AtomicInteger();
+    final MethodInterceptor countingInterceptor = new MethodInterceptor() {
+      public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+        count.incrementAndGet();
+        return methodInvocation.proceed();
+      }
+    };
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Object.class).toConstructor(constructor);
+        bindInterceptor(Matchers.any(), Matchers.any(), countingInterceptor);
+      }
+    });
+
+    D d = (D) injector.getInstance(Object.class);
+    d.hashCode();
+    d.hashCode();
+    assertEquals(2, count.get());
+  }
+/*end[AOP]*/
+
+  public void testInaccessibleConstructor() throws NoSuchMethodException {
+    final Constructor<E> constructor = E.class.getDeclaredConstructor(Stage.class);
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(E.class).toConstructor(constructor);
+      }
+    });
+
+    E e = injector.getInstance(E.class);
+    assertEquals(Stage.DEVELOPMENT, e.stage);
+  }
+
+  public void testToConstructorAndScopes() throws NoSuchMethodException {
+    final Constructor<F> constructor = F.class.getConstructor(Stage.class);
+
+    final Key<Object> d = Key.get(Object.class, named("D")); // default scoping
+    final Key<Object> s = Key.get(Object.class, named("S")); // singleton
+    final Key<Object> n = Key.get(Object.class, named("N")); // "N" instances
+    final Key<Object> r = Key.get(Object.class, named("R")); // a regular binding
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(d).toConstructor(constructor);
+        bind(s).toConstructor(constructor).in(Singleton.class);
+        bind(n).toConstructor(constructor).in(Scopes.NO_SCOPE);
+        bind(r).to(F.class);
+      }
+    });
+
+    assertDistinct(injector, 1, d, d, d, d);
+    assertDistinct(injector, 1, s, s, s, s);
+    assertDistinct(injector, 4, n, n, n, n);
+    assertDistinct(injector, 1, r, r, r, r);
+    assertDistinct(injector, 4, d, d, r, r, s, s, n);
+  }
+
+  public void assertDistinct(Injector injector, int expectedCount, Key<?>... keys) {
+    ImmutableSet.Builder<Object> builder = ImmutableSet.builder();
+    for (Key<?> k : keys) {
+      builder.add(injector.getInstance(k));
+    }
+    assertEquals(expectedCount, builder.build().size());
+  }
+
+  public void testToConstructorSpiData() throws NoSuchMethodException {
+    final Set<TypeLiteral<?>> heardTypes = Sets.newHashSet();
+
+    final Constructor<D> constructor = D.class.getConstructor(Stage.class);
+    final TypeListener listener = new TypeListener() {
+      public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+        if (!heardTypes.add(type)) {
+          fail("Heard " + type + " multiple times!");
+        }
+      }
+    };
+
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Object.class).toConstructor(constructor);
+        bind(D.class).toConstructor(constructor);
+        bindListener(Matchers.any(), listener);
+      }
+    });
+    
+    assertEquals(ImmutableSet.of(TypeLiteral.get(D.class)), heardTypes);
+  }
+
+  public void testInterfaceToImplementationConstructor() throws NoSuchMethodException {
+    final Constructor<CFoo> constructor = CFoo.class.getDeclaredConstructor();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(IFoo.class).toConstructor(constructor);
+      }
+    });
+
+    injector.getInstance(IFoo.class);
+  }
+
+  public static interface IFoo {}
+  public static class CFoo implements IFoo {}
+
+  public void testGetAllBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(D.class).toInstance(new D(Stage.PRODUCTION));
+        bind(Object.class).to(D.class);
+        getProvider(new Key<C<Stage>>() {});
+      }
+    });
+
+    Map<Key<?>,Binding<?>> bindings = injector.getAllBindings();
+    assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
+        Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}),
+        bindings.keySet());
+
+    // add a JIT binding
+    injector.getInstance(F.class);
+
+    Map<Key<?>,Binding<?>> bindings2 = injector.getAllBindings();
+    assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
+        Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}, Key.get(F.class)),
+        bindings2.keySet());
+
+    // the original map shouldn't have changed
+    assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
+        Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}),
+        bindings.keySet());
+
+    // check the bindings' values
+    assertEquals(injector, bindings.get(Key.get(Injector.class)).getProvider().get());
+  }
+
+  public void testGetAllServletBindings() throws Exception {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(F.class); // an explicit binding that uses a JIT binding for a constructor
+      }
+    });
+    injector.getAllBindings();
+  }
+
+  public static class C<T> {
+    private Stage stage;
+    private T t;
+    @Inject T anotherT;
+
+    public C(Stage stage, T t) {
+      this.stage = stage;
+      this.t = t;
+    }
+
+    @Inject C() {}
+  }
+
+  public static class D {
+    Stage stage;
+    public D(Stage stage) {
+      this.stage = stage;
+    }
+  }
+
+  private static class E {
+    Stage stage;
+    private E(Stage stage) {
+      this.stage = stage;
+    }
+  }
+
+  @Singleton
+  public static class F {
+    Stage stage;
+    @Inject public F(Stage stage) {
+      this.stage = stage;
+    }
+  }
+  
+  public void testTurkeyBaconProblemUsingToConstuctor() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @SuppressWarnings("unchecked")
+      @Override
+      public void configure() {
+        bind(Bacon.class).to(UncookedBacon.class);
+        bind(Bacon.class).annotatedWith(named("Turkey")).to(TurkeyBacon.class);
+        bind(Bacon.class).annotatedWith(named("Cooked")).toConstructor(
+            (Constructor)InjectionPoint.forConstructorOf(Bacon.class).getMember());
+      }
+    });
+    Bacon bacon = injector.getInstance(Bacon.class);
+    assertEquals(Food.PORK, bacon.getMaterial());
+    assertFalse(bacon.isCooked());
+    
+    Bacon turkeyBacon = injector.getInstance(Key.get(Bacon.class, named("Turkey")));
+    assertEquals(Food.TURKEY, turkeyBacon.getMaterial());
+    assertTrue(turkeyBacon.isCooked());
+    
+    Bacon cookedBacon = injector.getInstance(Key.get(Bacon.class, named("Cooked")));
+    assertEquals(Food.PORK, cookedBacon.getMaterial());
+    assertTrue(cookedBacon.isCooked());    
+  }
+  
+  enum Food { TURKEY, PORK }
+  
+  private static class Bacon {
+    public Food getMaterial() { return Food.PORK; }
+    public boolean isCooked() { return true; }
+  }
+
+  private static class TurkeyBacon extends Bacon {
+    public Food getMaterial() { return Food.TURKEY; }
+  }
+
+  private static class UncookedBacon extends Bacon {
+    public boolean isCooked() { return false; }
+  }
+}
diff --git a/core/test/com/google/inject/BoundInstanceInjectionTest.java b/core/test/com/google/inject/BoundInstanceInjectionTest.java
new file mode 100644
index 0000000..59fe8b2
--- /dev/null
+++ b/core/test/com/google/inject/BoundInstanceInjectionTest.java
@@ -0,0 +1,119 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.name.Named;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class BoundInstanceInjectionTest extends TestCase {
+
+  public void testInstancesAreInjected() throws CreationException {
+    final O o = new O();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(O.class).toInstance(o);
+        bind(int.class).toInstance(5);
+      }
+    });
+
+    assertEquals(5, o.fromMethod);
+  }
+
+  static class O {
+    int fromMethod;
+    @Inject
+    void setInt(int i) {
+      this.fromMethod = i;
+    }
+  }
+
+  public void testProvidersAreInjected() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(O.class).toProvider(new Provider<O>() {
+          @Inject int i;
+          public O get() {
+            O o = new O();
+            o.setInt(i);
+            return o;
+          }
+        });
+        bind(int.class).toInstance(5);
+      }
+    });
+
+    assertEquals(5, injector.getInstance(O.class).fromMethod);
+  }
+
+  public void testMalformedInstance() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(Object.class).toInstance(new MalformedInjectable());
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      Asserts.assertContains(expected.getMessage(), MalformedInjectable.class.getName(),
+          ".doublyAnnotated() has more than one ", "annotation annotated with @BindingAnnotation: ",
+          Named.class.getName() + " and " + Another.class.getName());
+    }
+  }
+
+  public void testMalformedProvider() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(String.class).toProvider(new MalformedProvider());
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      Asserts.assertContains(expected.getMessage(), MalformedProvider.class.getName(),
+          ".doublyAnnotated() has more than one ", "annotation annotated with @BindingAnnotation: ",
+          Named.class.getName() + " and " + Another.class.getName());
+    }
+  }
+
+  static class MalformedInjectable {
+    @Inject void doublyAnnotated(@Named("a") @Another String unused) {}
+  }
+
+  static class MalformedProvider implements Provider<String> {
+    @Inject void doublyAnnotated(@Named("a") @Another String s) {}
+
+    public String get() {
+      return "a";
+    }
+  }
+
+  @BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
+  public @interface Another {}
+}
diff --git a/core/test/com/google/inject/BoundProviderTest.java b/core/test/com/google/inject/BoundProviderTest.java
new file mode 100644
index 0000000..5fc46f4
--- /dev/null
+++ b/core/test/com/google/inject/BoundProviderTest.java
@@ -0,0 +1,102 @@
+/**
+ * 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 com.google.inject;
+
+import junit.framework.TestCase;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class BoundProviderTest extends TestCase {
+
+  public void testFooProvider() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class).toProvider(FooProvider.class);
+      }
+    });
+
+    Foo a = injector.getInstance(Foo.class);
+    Foo b = injector.getInstance(Foo.class);
+
+    assertEquals(0, a.i);
+    assertEquals(0, b.i);
+    assertNotNull(a.bar);
+    assertNotNull(b.bar);
+    assertNotSame(a.bar, b.bar);
+  }
+
+  public void testSingletonFooProvider() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class).toProvider(SingletonFooProvider.class);
+      }
+    });
+
+    Foo a = injector.getInstance(Foo.class);
+    Foo b = injector.getInstance(Foo.class);
+
+    assertEquals(0, a.i);
+    assertEquals(1, b.i);
+    assertNotNull(a.bar);
+    assertNotNull(b.bar);
+    assertSame(a.bar, b.bar);
+  }
+
+  static class Bar {}
+
+  static class Foo {
+    final Bar bar;
+    final int i;
+
+    Foo(Bar bar, int i) {
+      this.bar = bar;
+      this.i = i;
+    }
+  }
+
+  static class FooProvider implements Provider<Foo> {
+
+    final Bar bar;
+    int count = 0;
+
+    @Inject
+    public FooProvider(Bar bar) {
+      this.bar = bar;
+    }
+
+    public Foo get() {
+      return new Foo(this.bar, count++);
+    }
+  }
+
+  @Singleton
+  static class SingletonFooProvider implements Provider<Foo> {
+
+    final Bar bar;
+    int count = 0;
+
+    @Inject
+    public SingletonFooProvider(Bar bar) {
+      this.bar = bar;
+    }
+
+    public Foo get() {
+      return new Foo(this.bar, count++);
+    }
+  }
+}
diff --git a/core/test/com/google/inject/CircularDependencyTest.java b/core/test/com/google/inject/CircularDependencyTest.java
new file mode 100644
index 0000000..2b67f7b
--- /dev/null
+++ b/core/test/com/google/inject/CircularDependencyTest.java
@@ -0,0 +1,598 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class CircularDependencyTest extends TestCase {
+  
+  @Override
+  protected void setUp() throws Exception {
+    AImpl.nextId = 0;
+    BImpl.nextId = 0;
+  }
+
+  public void testCircularlyDependentConstructors()
+      throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(A.class).to(AImpl.class);
+        bind(B.class).to(BImpl.class);
+      }
+    });
+    assertCircularDependencies(injector);
+  }
+  
+  public void testCircularlyDependentConstructorsWithProviderMethods()
+      throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {}
+      
+      @Provides @Singleton A a(B b) { return new AImpl(b); }
+      @Provides B b(A a) { return new BImpl(a); }
+    });
+    assertCircularDependencies(injector);
+  }
+  
+  public void testCircularlyDependentConstructorsWithProviderInstances()
+      throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(A.class).toProvider(new Provider<A>() {
+          @Inject Provider<B> bp;
+          public A get() {
+            return new AImpl(bp.get());
+          }
+        }).in(Singleton.class);
+        bind(B.class).toProvider(new Provider<B>() {
+          @Inject Provider<A> ap;
+          public B get() {
+            return new BImpl(ap.get());
+          }
+        });
+      }
+    });
+    assertCircularDependencies(injector);
+  }
+  
+  public void testCircularlyDependentConstructorsWithProviderKeys()
+      throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(A.class).toProvider(AP.class).in(Singleton.class);
+        bind(B.class).toProvider(BP.class);
+      }
+    });
+    assertCircularDependencies(injector);
+  }
+  
+  public void testCircularlyDependentConstructorsWithProvidedBy()
+      throws CreationException {
+    Injector injector = Guice.createInjector();
+    assertCircularDependencies(injector);
+  }
+  
+  private void assertCircularDependencies(Injector injector) {
+    A a = injector.getInstance(A.class);
+    assertNotNull(a.getB().getA());
+    assertEquals(0, a.id());
+    assertEquals(a.id(), a.getB().getA().id());
+    assertEquals(0, a.getB().id());
+    assertEquals(1, AImpl.nextId);
+    assertEquals(1, BImpl.nextId);
+    assertSame(a, injector.getInstance(A.class));
+  }
+
+  @ProvidedBy(AutoAP.class)
+  public interface A {
+    B getB();
+    int id();
+  }
+
+  @Singleton
+  static class AImpl implements A {
+    static int nextId;
+    int id = nextId++;
+    
+    final B b;
+    @Inject public AImpl(B b) {
+      this.b = b;
+    }
+    public int id() {
+      return id;
+    }
+    public B getB() {
+      return b;
+    }
+  }
+  
+  static class AP implements Provider<A> {
+    @Inject Provider<B> bp;
+    public A get() {
+      return new AImpl(bp.get());
+    }
+  }
+  
+  @Singleton
+  static class AutoAP implements Provider<A> {
+    @Inject Provider<B> bp;
+    A a;
+    
+    public A get() {
+      if (a == null) {
+        a = new AImpl(bp.get());
+      }
+      return a;
+    }
+  }
+
+  @ProvidedBy(BP.class)
+  public interface B {
+    A getA();
+    int id();
+  }
+
+  static class BImpl implements B {
+    static int nextId;
+    int id = nextId++;
+    
+    final A a;
+    @Inject public BImpl(A a) {
+      this.a = a;
+    }
+    public int id() {
+      return id;
+    }
+    public A getA() {
+      return a;
+    }
+  }
+  
+  static class BP implements Provider<B> {
+    Provider<A> ap;
+    @Inject BP(Provider<A> ap) {
+      this.ap = ap;
+    }
+    public B get() {
+      return new BImpl(ap.get());
+    }
+  }
+
+  public void testUnresolvableCircularDependency() {
+    try {
+      Guice.createInjector().getInstance(C.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + C.class.getName() + " to support a circular dependency, ",
+          "but it is not an interface.");
+    }
+  }
+  
+  public void testUnresolvableCircularDependenciesWithProviderInstances() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {}        
+        @Provides C c(D d) { return null; }
+        @Provides D d(C c) { return null; }
+      }).getInstance(C.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + C.class.getName() + " to support a circular dependency, ",
+          "but it is not an interface.");
+    }
+  }
+  
+  public void testUnresolvableCircularDependenciesWithProviderKeys() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(C2.class).toProvider(C2P.class);
+          bind(D2.class).toProvider(D2P.class);
+        }
+      }).getInstance(C2.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + C2.class.getName() + " to support a circular dependency, ",
+          "but it is not an interface.");
+    }
+  }
+  
+  public void testUnresolvableCircularDependenciesWithProvidedBy() {
+    try {
+      Guice.createInjector().getInstance(C2.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + C2.class.getName() + " to support a circular dependency, ",
+          "but it is not an interface.");
+    }
+  }
+
+  static class C {
+    @Inject C(D d) {}
+  }
+  static class D {
+    @Inject D(C c) {}
+  }
+  
+  static class C2P implements Provider<C2> {
+    @Inject Provider<D2> dp;
+    public C2 get() {
+      dp.get();
+      return null;
+    }
+  }
+  static class D2P implements Provider<D2> {
+    @Inject Provider<C2> cp;
+    public D2 get() {
+      cp.get();
+      return null;
+    }
+  }
+  @ProvidedBy(C2P.class)
+  static class C2 {
+    @Inject C2(D2 d) {}
+  }
+  @ProvidedBy(D2P.class)
+  static class D2 {
+    @Inject D2(C2 c) {}
+  }
+  
+  public void testDisabledCircularDependency() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().disableCircularProxies();
+        }
+      }).getInstance(C.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + C.class.getName() + " to support a circular dependency, ",
+          "but circular proxies are disabled.");
+    }
+  }
+  
+  public void testDisabledCircularDependenciesWithProviderInstances() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          binder().disableCircularProxies();
+        }        
+        @Provides C c(D d) { return null; }
+        @Provides D d(C c) { return null; }
+      }).getInstance(C.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + C.class.getName() + " to support a circular dependency, ",
+          "but circular proxies are disabled.");
+    }
+  }
+  
+  public void testDisabledCircularDependenciesWithProviderKeys() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          binder().disableCircularProxies();
+          bind(C2.class).toProvider(C2P.class);
+          bind(D2.class).toProvider(D2P.class);
+        }
+      }).getInstance(C2.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + C2.class.getName() + " to support a circular dependency, ",
+          "but circular proxies are disabled.");
+    }
+  }
+  
+  public void testDisabledCircularDependenciesWithProvidedBy() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().disableCircularProxies();
+        }
+      }).getInstance(C2.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + C2.class.getName() + " to support a circular dependency, ",
+          "but circular proxies are disabled.");
+    }
+  }
+
+  /**
+   * As reported by issue 349, we give a lousy trace when a class is circularly
+   * dependent on itself in multiple ways.
+   */
+  public void testCircularlyDependentMultipleWays() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        binder.bind(A.class).to(E.class);
+        binder.bind(B.class).to(E.class);
+      }
+    });
+    injector.getInstance(A.class);
+  }
+  
+  public void testDisablingCircularProxies() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        binder().disableCircularProxies();
+        binder.bind(A.class).to(E.class);
+        binder.bind(B.class).to(E.class);
+      }
+    });
+    
+    try {
+      injector.getInstance(A.class);
+      fail("expected exception");
+    } catch(ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + A.class.getName() + " to support a circular dependency, but circular proxies are disabled", 
+          "Tried proxying " + B.class.getName() + " to support a circular dependency, but circular proxies are disabled");
+    }
+  }
+
+  @Singleton
+  static class E implements A, B {
+    @Inject
+    public E(A a, B b) {}
+
+    public B getB() {
+      return this;
+    }
+
+    public A getA() {
+      return this;
+    }
+    
+    public int id() {
+      return 0;
+    }
+  }
+
+
+  public void testCircularDependencyProxyDelegateNeverInitialized() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(F.class).to(RealF.class);
+        bind(G.class).to(RealG.class);
+      }
+    });
+    F f = injector.getInstance(F.class);
+    assertEquals("F", f.g().f().toString());
+    assertEquals("G", f.g().f().g().toString());
+
+  }
+
+  public interface F {
+    G g();
+  }
+
+  @Singleton
+  public static class RealF implements F {
+    private final G g;
+    @Inject RealF(G g) {
+      this.g = g;
+    }
+
+    public G g() {
+      return g;
+    }
+
+    @Override public String toString() {
+      return "F";
+    }
+  }
+
+  public interface G {
+    F f();
+  }
+
+  @Singleton
+  public static class RealG implements G {
+    private final F f;
+    @Inject RealG(F f) {
+      this.f = f;
+    }
+
+    public F f() {
+      return f;
+    }
+
+    @Override public String toString() {
+      return "G";
+    }
+  }
+  
+  /**
+   * Tests that ProviderInternalFactory can detect circular dependencies
+   * before it gets to Scopes.SINGLETON.  This is especially important
+   * because the failure in Scopes.SINGLETON doesn't have enough context to
+   * provide a decent error message.
+   */
+  public void testCircularDependenciesDetectedEarlyWhenDependenciesHaveDifferentTypes() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Number.class).to(Integer.class);
+      }
+      
+      @Provides @Singleton Integer provideInteger(List list) { 
+        return new Integer(2);
+      }
+      
+      @Provides List provideList(Integer integer) {
+        return new ArrayList();
+      }
+    });
+    try {
+      injector.getInstance(Number.class);
+      fail();
+    } catch(ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "Tried proxying " + Integer.class.getName() + " to support a circular dependency, ",
+          "but it is not an interface.");      
+    }
+  }
+  
+  public void testPrivateModulesDontTriggerCircularErrorsInProviders() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new PrivateModule() {
+          @Override
+          protected void configure() {
+            bind(Foo.class);
+            expose(Foo.class);
+          }
+          @Provides String provideString(Bar bar) {
+            return new String("private 1, " + bar.string);
+          }
+        });
+        install(new PrivateModule() {
+          @Override
+          protected void configure() {
+            bind(Bar.class);
+            expose(Bar.class);
+          }
+          @Provides String provideString() {
+            return new String("private 2");
+          }
+        });
+      }
+    });
+    Foo foo = injector.getInstance(Foo.class);
+    assertEquals("private 1, private 2", foo.string);
+  }
+  static class Foo {
+    @Inject String string;
+  }
+  static class Bar {
+    @Inject String string;
+  }
+  
+  /**
+   * When Scope Providers call their unscoped Provider's get() methods are
+   * called, it's possible that the result is a circular proxy designed for one
+   * specific parameter (not for all possible parameters). But custom scopes
+   * typically cache the results without checking to see if the result is a
+   * proxy. This leads to caching a result that is unsuitable for reuse for
+   * other parameters.
+   * 
+   * This means that custom proxies have to do an
+   *   {@code if(Scopes.isCircularProxy(..))}
+   * in order to avoid exceptions.
+   */
+  public void testCustomScopeCircularProxies() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindScope(SimpleSingleton.class, new BasicSingleton());
+        bind(H.class).to(HImpl.class);
+        bind(I.class).to(IImpl.class);
+        bind(J.class).to(JImpl.class);
+      }
+    });
+    
+    // The reason this happens is because the Scope gets these requests, in order:
+    // entry: Key<IImpl> (1 - from getInstance call)
+    // entry: Key<HImpl>
+    // entry: Key<IImpl> (2 - circular dependency from HImpl)
+    // result of 2nd Key<IImpl> - a com.google.inject.$Proxy, because it's a circular proxy
+    // result of Key<HImpl> - an HImpl
+    // entry: Key<JImpl>
+    // entry: Key<IImpl> (3 - another circular dependency, this time from JImpl)    
+    // At this point, if the first Key<Impl> result was cached, our cache would have
+    //  Key<IImpl> caching to an instanceof of I, but not an an instanceof of IImpl.
+    // If returned this, it would result in cglib giving a ClassCastException or
+    // java reflection giving an IllegalArgumentException when filling in parameters
+    // for the constructor, because JImpl wants an IImpl, not an I.
+    
+    try {
+      injector.getInstance(IImpl.class);
+      fail();
+    } catch(ProvisionException pe) {
+      assertContains(Iterables.getOnlyElement(pe.getErrorMessages()).getMessage(),
+          "Tried proxying " + IImpl.class.getName()
+          + " to support a circular dependency, but it is not an interface.");
+    }
+  }
+  
+  interface H {}
+  interface I {}
+  interface J {}
+  @SimpleSingleton
+  static class HImpl implements H {
+     @Inject HImpl(I i) {}     
+  }
+  @SimpleSingleton
+  static class IImpl implements I {
+     @Inject IImpl(HImpl i, J j) {}
+  }
+  @SimpleSingleton
+  static class JImpl implements J {
+     @Inject JImpl(IImpl i) {}
+  }
+  
+  @Target({ ElementType.TYPE, ElementType.METHOD })
+  @Retention(RUNTIME)
+  @ScopeAnnotation
+  public @interface SimpleSingleton {}
+  public static class BasicSingleton implements Scope {
+    private static Map<Key, Object> cache = Maps.newHashMap();
+    public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
+      return new Provider<T>() {
+        @SuppressWarnings("unchecked")
+        public T get() {
+          if (!cache.containsKey(key)) {
+            T t = unscoped.get();
+            if (Scopes.isCircularProxy(t)) {
+              return t;
+            }
+            cache.put(key, t);
+          }
+          return (T)cache.get(key);
+        }
+      };
+    }
+  }
+}
diff --git a/core/test/com/google/inject/DuplicateBindingsTest.java b/core/test/com/google/inject/DuplicateBindingsTest.java
new file mode 100644
index 0000000..27a2fd1
--- /dev/null
+++ b/core/test/com/google/inject/DuplicateBindingsTest.java
@@ -0,0 +1,576 @@
+/**
+ * Copyright (C) 2010 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.inject;
+
+import static com.google.inject.Asserts.*;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+import com.google.inject.name.Named;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * A suite of tests for duplicate bindings.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class DuplicateBindingsTest extends TestCase {
+  
+  private FooImpl foo = new FooImpl();
+  private Provider<Foo> pFoo = Providers.<Foo>of(new FooImpl());
+  private Class<? extends Provider<? extends Foo>> pclFoo = FooProvider.class;
+  private Class<? extends Foo> clFoo = FooImpl.class;
+  private Constructor<FooImpl> cFoo = FooImpl.cxtor();
+
+  public void testDuplicateBindingsAreIgnored() {
+    Injector injector = Guice.createInjector(
+        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
+        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+    List<Key<?>> bindings = Lists.newArrayList(injector.getAllBindings().keySet());
+    removeBasicBindings(bindings);
+    
+    // Ensure only one binding existed for each type.
+    assertTrue(bindings.remove(Key.get(Foo.class, named("instance"))));
+    assertTrue(bindings.remove(Key.get(Foo.class, named("pInstance"))));
+    assertTrue(bindings.remove(Key.get(Foo.class, named("pKey"))));
+    assertTrue(bindings.remove(Key.get(Foo.class, named("linkedKey"))));
+    assertTrue(bindings.remove(Key.get(FooImpl.class)));
+    assertTrue(bindings.remove(Key.get(Foo.class, named("constructor"))));
+    assertTrue(bindings.remove(Key.get(FooProvider.class))); // JIT binding
+    assertTrue(bindings.remove(Key.get(Foo.class, named("providerMethod"))));
+    
+    assertEquals(bindings.toString(), 0, bindings.size());
+  }
+  
+  public void testElementsDeduplicate() {
+    List<Element> elements = Elements.getElements(
+        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
+        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+    assertEquals(14, elements.size());
+    assertEquals(7, new LinkedHashSet<Element>(elements).size());
+  }
+  
+  public void testProviderMethodsFailIfInstancesDiffer() {
+    try {
+      Guice.createInjector(new FailingProviderModule(), new FailingProviderModule());
+      fail("should have failed");
+    } catch(CreationException ce) {
+      assertContains(ce.getMessage(),
+          "A binding to " + Foo.class.getName() + " was already configured " +
+          "at " + FailingProviderModule.class.getName(),
+          "at " + FailingProviderModule.class.getName()
+          );
+    }
+  }
+  
+  public void testSameScopeInstanceIgnored() {
+    Guice.createInjector(
+        new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo),
+        new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+    
+    Guice.createInjector(
+        new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo),
+        new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+  }
+  
+  public void testSameScopeAnnotationIgnored() {
+    Guice.createInjector(
+        new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo),
+        new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+  }
+  
+  public void testMixedAnnotationAndScopeForSingletonIgnored() {
+    Guice.createInjector(
+        new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo),
+        new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+  }
+  
+  public void testMixedScopeAndUnscopedIgnored() {
+    Guice.createInjector(
+        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
+        new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+  }
+
+  public void testMixedScopeFails() {
+    try {
+      Guice.createInjector(
+          new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
+          new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo)
+      );
+      fail("expected exception");
+    } catch(CreationException ce) {
+      String segment1 = "A binding to " + Foo.class.getName() + " annotated with "
+          + named("pInstance") + " was already configured at " + SimpleModule.class.getName();
+      String segment2 = "A binding to " + Foo.class.getName() + " annotated with " + named("pKey")
+          + " was already configured at " + SimpleModule.class.getName();
+      String segment3 = "A binding to " + Foo.class.getName() + " annotated with " 
+          + named("constructor") + " was already configured at " + SimpleModule.class.getName();
+      String segment4 = "A binding to " + FooImpl.class.getName() + " was already configured at "
+          + SimpleModule.class.getName();
+      String atSegment = "at " + ScopedModule.class.getName();
+      if (isIncludeStackTraceOff()) {
+        assertContains(ce.getMessage(), segment1 , atSegment, segment2, atSegment, segment3,
+            atSegment, segment4, atSegment);
+      } else {
+        assertContains(ce.getMessage(), segment1 , atSegment, segment2, atSegment, segment4,
+            atSegment, segment3, atSegment);
+      }
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public void testMixedTargetsFails() {
+    try {
+      Guice.createInjector(
+          new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
+          new SimpleModule(new FooImpl(), Providers.<Foo>of(new FooImpl()), 
+              (Class)BarProvider.class, (Class)Bar.class, (Constructor)Bar.cxtor())
+      );
+      fail("expected exception");
+    } catch(CreationException ce) {
+      assertContains(ce.getMessage(), 
+          "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(),
+          "at " + SimpleModule.class.getName(), 
+          "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(),
+          "at " + SimpleModule.class.getName(), 
+          "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(),
+          "at " + SimpleModule.class.getName(),
+          "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(),
+          "at " + SimpleModule.class.getName());
+    }
+  }
+  
+  public void testExceptionInEqualsThrowsCreationException() {
+    try {
+      Guice.createInjector(new ThrowingModule(), new ThrowingModule());
+      fail("expected exception");
+    } catch(CreationException ce) {
+      assertContains(ce.getMessage(),
+          "A binding to " + Foo.class.getName() + " was already configured at " + ThrowingModule.class.getName(),
+          "and an error was thrown while checking duplicate bindings.  Error: java.lang.RuntimeException: Boo!",
+          "at " + ThrowingModule.class.getName());
+    }
+  }
+  
+  public void testChildInjectorDuplicateParentFail() {
+    Injector injector = Guice.createInjector(
+        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+    
+    try {
+      injector.createChildInjector(
+          new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
+      );
+      fail("expected exception");
+    } catch(CreationException ce) {
+      assertContains(ce.getMessage(), 
+          "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(),
+          "at " + SimpleModule.class.getName(), 
+          "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(),
+          "at " + SimpleModule.class.getName(), 
+          "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(),
+          "at " + SimpleModule.class.getName(),
+          "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(),
+          "at " + SimpleModule.class.getName(),
+          "A binding to " + Foo.class.getName() + " annotated with " + named("providerMethod") + " was already configured at " + SimpleProviderModule.class.getName(),
+          "at " + SimpleProviderModule.class.getName()
+          );
+    } 
+    
+    
+  }
+  
+  public void testDuplicatesSolelyInChildIgnored() {
+    Injector injector = Guice.createInjector();
+    injector.createChildInjector(
+        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
+        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+  }
+  
+  public void testDifferentBindingTypesFail() {
+    List<Element> elements = Elements.getElements(
+        new FailedModule(foo, pFoo, pclFoo, clFoo, cFoo)
+    );
+    
+    // Make sure every combination of the elements with another element fails.
+    // This ensures that duplication checks the kind of binding also.
+    for(Element e1 : elements) {
+      for(Element e2: elements) {
+        // if they're the same, this shouldn't fail.
+        try {
+          Guice.createInjector(Elements.getModule(Arrays.asList(e1, e2)));
+          if(e1 != e2) {
+            fail("must fail!");
+          }
+        } catch(CreationException expected) {
+          if(e1 != e2) {
+            assertContains(expected.getMessage(),
+                "A binding to " + Foo.class.getName() + " was already configured at " + FailedModule.class.getName(),
+                "at " + FailedModule.class.getName());
+          } else {
+            throw expected;
+          }
+        }
+      }
+    }
+  }
+  
+  public void testJitBindingsAreCheckedAfterConversions() {
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(A.class);
+       bind(A.class).to(RealA.class);
+      }
+    });
+  }
+  
+  public void testEqualsNotCalledByDefaultOnInstance() {
+    final HashEqualsTester a = new HashEqualsTester();
+    a.throwOnEquals = true;
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(String.class);
+       bind(HashEqualsTester.class).toInstance(a);
+      }
+    });
+  }
+  
+  public void testEqualsNotCalledByDefaultOnProvider() {
+    final HashEqualsTester a = new HashEqualsTester();
+    a.throwOnEquals = true;
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(String.class);
+       bind(Object.class).toProvider(a);
+      }
+    });
+  }
+  
+  public void testHashcodeNeverCalledOnInstance() {
+    final HashEqualsTester a = new HashEqualsTester();
+    a.throwOnHashcode = true;
+    a.equality = "test";
+    
+    final HashEqualsTester b = new HashEqualsTester();
+    b.throwOnHashcode = true;
+    b.equality = "test";
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(String.class);
+       bind(HashEqualsTester.class).toInstance(a);
+       bind(HashEqualsTester.class).toInstance(b);
+      }
+    });
+  }
+  
+  public void testHashcodeNeverCalledOnProviderInstance() {
+    final HashEqualsTester a = new HashEqualsTester();
+    a.throwOnHashcode = true;
+    a.equality = "test";
+    
+    final HashEqualsTester b = new HashEqualsTester();
+    b.throwOnHashcode = true;
+    b.equality = "test";
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(String.class);
+       bind(Object.class).toProvider(a);
+       bind(Object.class).toProvider(b);
+      }
+    });
+  }
+
+  private static class RealA extends A {}
+  @ImplementedBy(RealA.class) private static class A {}
+  
+  private void removeBasicBindings(Collection<Key<?>> bindings) {
+    bindings.remove(Key.get(Injector.class));
+    bindings.remove(Key.get(Logger.class));
+    bindings.remove(Key.get(Stage.class));
+  }
+  
+  private static class ThrowingModule extends AbstractModule {
+    @Override
+    protected void configure() {
+      bind(Foo.class).toInstance(new Foo() {
+        @Override
+        public boolean equals(Object obj) {
+          throw new RuntimeException("Boo!");
+        }
+      });
+    }
+  }
+  
+  private static abstract class FooModule extends AbstractModule {
+    protected final FooImpl foo;
+    protected final Provider<Foo> pFoo;
+    protected final Class<? extends Provider<? extends Foo>> pclFoo;
+    protected final Class<? extends Foo> clFoo;
+    protected final Constructor<FooImpl> cFoo;
+    
+    FooModule(FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo,
+        Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo) {
+      this.foo = foo;
+      this.pFoo = pFoo;
+      this.pclFoo = pclFoo;
+      this.clFoo = clFoo;
+      this.cFoo = cFoo;
+    }    
+  }
+  
+  private static class FailedModule extends FooModule {
+    FailedModule(FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo,
+        Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo) {
+      super(foo, pFoo, pclFoo, clFoo, cFoo);
+    }
+    
+    protected void configure() {
+      // InstanceBinding
+      bind(Foo.class).toInstance(foo);
+      
+      // ProviderInstanceBinding
+      bind(Foo.class).toProvider(pFoo);
+      
+      // ProviderKeyBinding
+      bind(Foo.class).toProvider(pclFoo);
+      
+      // LinkedKeyBinding
+      bind(Foo.class).to(clFoo);
+      
+      // ConstructorBinding
+      bind(Foo.class).toConstructor(cFoo);
+    }
+    
+    @Provides Foo foo() {
+      return null;
+    }
+  }
+  
+  private static class FailingProviderModule extends AbstractModule {
+    @Override protected void configure() {}
+
+    @Provides Foo foo() {
+      return null;
+    }
+  }
+
+  private static class SimpleProviderModule extends AbstractModule {
+    @Override protected void configure() {}
+
+    @Provides @Named("providerMethod") Foo foo() {
+      return null;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      return obj.getClass() == getClass();
+    }
+  }  
+  
+  private static class SimpleModule extends FooModule {
+    SimpleModule(FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo,
+        Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo) {
+      super(foo, pFoo, pclFoo, clFoo, cFoo);
+    }
+    
+    protected void configure() {
+      // InstanceBinding
+      bind(Foo.class).annotatedWith(named("instance")).toInstance(foo);
+      
+      // ProviderInstanceBinding
+      bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo);
+      
+      // ProviderKeyBinding
+      bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo);
+      
+      // LinkedKeyBinding
+      bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo);
+      
+      // UntargettedBinding / ConstructorBinding
+      bind(FooImpl.class);
+      
+      // ConstructorBinding
+      bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo);
+
+      // ProviderMethod
+      // (reconstructed from an Element to ensure it doesn't get filtered out
+      //  by deduplicating Modules)
+      install(Elements.getModule(Elements.getElements(new SimpleProviderModule())));
+    }
+  }
+  
+  private static class ScopedModule extends FooModule {
+    private final Scope scope;
+
+    ScopedModule(Scope scope, FooImpl foo, Provider<Foo> pFoo,
+        Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo,
+        Constructor<FooImpl> cFoo) {
+      super(foo, pFoo, pclFoo, clFoo, cFoo);
+      this.scope = scope;
+    }
+    
+    protected void configure() {
+      // ProviderInstanceBinding
+      bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope);
+      
+      // ProviderKeyBinding
+      bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope);
+      
+      // LinkedKeyBinding
+      bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope);
+      
+      // UntargettedBinding / ConstructorBinding
+      bind(FooImpl.class).in(scope);
+      
+      // ConstructorBinding
+      bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope);
+    }
+  }
+  
+  private static class AnnotatedScopeModule extends FooModule {
+    private final Class<? extends Annotation> scope;
+
+    AnnotatedScopeModule(Class<? extends Annotation> scope, FooImpl foo, Provider<Foo> pFoo,
+        Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo,
+        Constructor<FooImpl> cFoo) {
+      super(foo, pFoo, pclFoo, clFoo, cFoo);
+      this.scope = scope;
+    }
+    
+    
+    protected void configure() {
+      // ProviderInstanceBinding
+      bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope);
+      
+      // ProviderKeyBinding
+      bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope);
+      
+      // LinkedKeyBinding
+      bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope);
+      
+      // UntargettedBinding / ConstructorBinding
+      bind(FooImpl.class).in(scope);
+      
+      // ConstructorBinding
+      bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope);
+    }
+  }  
+  
+  private static interface Foo {}
+  private static class FooImpl implements Foo {
+    @Inject public FooImpl() {}
+    
+    private static Constructor<FooImpl> cxtor() {
+      try {
+        return FooImpl.class.getConstructor();
+      } catch (SecurityException e) {
+        throw new RuntimeException(e);
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }  
+  private static class FooProvider implements Provider<Foo> {
+    public Foo get() {
+      return new FooImpl();
+    }
+  }
+  
+  private static class Bar implements Foo {
+    @Inject public Bar() {}
+    
+    private static Constructor<Bar> cxtor() {
+      try {
+        return Bar.class.getConstructor();
+      } catch (SecurityException e) {
+        throw new RuntimeException(e);
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }  
+  private static class BarProvider implements Provider<Foo> {
+    public Foo get() {
+      return new Bar();
+    }
+  }
+  
+  private static class HashEqualsTester implements Provider<Object> {
+    private String equality;
+    private boolean throwOnEquals;
+    private boolean throwOnHashcode;
+    
+    @Override
+    public boolean equals(Object obj) {
+      if (throwOnEquals) {
+        throw new RuntimeException();
+      } else if (obj instanceof HashEqualsTester) {
+        HashEqualsTester o = (HashEqualsTester)obj;
+        if(o.throwOnEquals) {
+          throw new RuntimeException();
+        }
+        if(equality == null && o.equality == null) {
+          return this == o;
+        } else {
+          return Objects.equal(equality, o.equality);
+        }
+      } else {
+        return false;
+      }
+    }
+    
+    @Override
+    public int hashCode() {
+      if(throwOnHashcode) {
+        throw new RuntimeException();
+      } else {
+        return super.hashCode();
+      }
+    }
+    
+    public Object get() {
+      return new Object();
+    }
+  }
+  
+}
diff --git a/core/test/com/google/inject/EagerSingletonTest.java b/core/test/com/google/inject/EagerSingletonTest.java
new file mode 100644
index 0000000..d18f194
--- /dev/null
+++ b/core/test/com/google/inject/EagerSingletonTest.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 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.inject;
+
+import junit.framework.TestCase;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class EagerSingletonTest extends TestCase {
+
+  @Override public void setUp() {
+    A.instanceCount = 0;
+    B.instanceCount = 0;
+    C.instanceCount = 0;
+  }
+
+  public void testJustInTimeEagerSingletons() {
+    Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
+      protected void configure() {
+        // create a just-in-time binding for A
+        getProvider(A.class);
+
+        // create a just-in-time binding for C
+        requestInjection(new Object() {
+          @Inject void inject(Injector injector) {
+            injector.getInstance(C.class);
+          }
+        });
+      }
+    });
+
+    assertEquals(1, A.instanceCount);
+    assertEquals("Singletons discovered when creating singletons should not be built eagerly",
+        0, B.instanceCount);
+    assertEquals(1, C.instanceCount);
+  }
+
+  public void testJustInTimeSingletonsAreNotEager() {
+    Injector injector = Guice.createInjector(Stage.PRODUCTION);
+    injector.getProvider(B.class);
+    assertEquals(0, B.instanceCount);
+  }
+
+  public void testChildEagerSingletons() {
+    Injector parent = Guice.createInjector(Stage.PRODUCTION);
+    parent.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(D.class).to(C.class);
+      }
+    });
+
+    assertEquals(1, C.instanceCount);
+  }
+
+  @Singleton
+  static class A {
+    static int instanceCount = 0;
+    int instanceId = instanceCount++;
+
+    @Inject A(Injector injector) {
+      injector.getProvider(B.class);
+    }
+  }
+
+  @Singleton
+  static class B {
+    static int instanceCount = 0;
+    int instanceId = instanceCount++;
+  }
+
+  @Singleton
+  static class C implements D {
+    static int instanceCount = 0;
+    int instanceId = instanceCount++;
+  }
+
+  private static interface D {}
+}
diff --git a/core/test/com/google/inject/ErrorHandlingTest.java b/core/test/com/google/inject/ErrorHandlingTest.java
new file mode 100644
index 0000000..19161ca
--- /dev/null
+++ b/core/test/com/google/inject/ErrorHandlingTest.java
@@ -0,0 +1,150 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.List;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ErrorHandlingTest {
+
+  public static void main(String[] args) throws CreationException {
+    try {
+      Guice.createInjector(new MyModule());
+    }
+    catch (CreationException e) {
+      e.printStackTrace();
+      System.err.println("--");
+    }
+
+    Injector bad = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toProvider(new Provider<String>() {
+          public String get() {
+            return null;
+          }
+        });
+      }
+    });
+    try {
+      bad.getInstance(String.class);
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+      System.err.println("--");
+    }
+    try {
+      bad.getInstance(NeedsString.class);
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+      System.err.println("--");
+    }
+  }
+
+  static class NeedsString {
+    @Inject String mofo;
+  }
+
+  @Inject @Named("missing")
+  static List<String> missing = null;
+
+  static class Foo {
+    @Inject
+    public Foo(Runnable r) {}
+
+    @Inject void setNames(List<String> names) {}
+  }
+
+  static class Bar {
+    // Invalid constructor.
+    Bar(String s) {}
+
+    @Inject void setNumbers(@Named("numbers") List<Integer> numbers) {}
+
+    @Inject void bar(@Named("foo") String s) {}
+  }
+
+  static class Tee {
+    @Inject String s;
+
+    @Inject void tee(String s, int i) {}
+
+    @Inject Invalid invalid;
+  }
+
+  static class Invalid {
+    Invalid(String s) {}
+  }
+
+  @SuppressWarnings("MoreThanOneScopeAnnotationOnClass") // suppress compiler error to test
+  @Singleton 
+  @GoodScope
+  static class TooManyScopes {
+  }
+
+  @Target(ElementType.TYPE)
+  @Retention(RUNTIME)
+  @ScopeAnnotation
+  @interface GoodScope {}
+
+  @interface BadScope {}
+
+  @ImplementedBy(String.class)
+  interface I {}
+
+  static class MyModule extends AbstractModule {
+    protected void configure() {
+      bind(Runnable.class);
+      bind(Foo.class);
+      bind(Bar.class);
+      bind(Tee.class);
+      bind(new TypeLiteral<List<String>>() {});
+      bind(String.class).annotatedWith(Names.named("foo")).in(Named.class);
+      bind(Key.get(Runnable.class)).to(Key.get(Runnable.class));
+      bind(TooManyScopes.class);
+      bindScope(BadScope.class, Scopes.SINGLETON);
+      bind(Object.class).toInstance(new Object() {
+        @Inject void foo() {
+          throw new RuntimeException();
+        }
+      });
+      requestStaticInjection(ErrorHandlingTest.class);
+
+      addError("I don't like %s", "you");
+      
+      Object o = "2";
+      try {
+        Integer i = (Integer) o;
+      } catch (Exception e) {
+        addError(e);
+      }
+
+      bind(Module.class).toInstance(this);
+      bind(I.class);
+    }
+  }
+}
diff --git a/core/test/com/google/inject/GenericInjectionTest.java b/core/test/com/google/inject/GenericInjectionTest.java
new file mode 100644
index 0000000..51a1cb1
--- /dev/null
+++ b/core/test/com/google/inject/GenericInjectionTest.java
@@ -0,0 +1,187 @@
+/**
+ * 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 com.google.inject;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.util.Modules;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class GenericInjectionTest extends TestCase {
+
+  public void testGenericInjection() throws CreationException {
+    final List<String> names = Arrays.asList("foo", "bar", "bob");
+
+    Injector injector = Guice.createInjector((Module) new AbstractModule() {
+      protected void configure() {
+        bind(new TypeLiteral<List<String>>() {}).toInstance(names);
+      }
+    });
+
+    Foo foo = injector.getInstance(Foo.class);
+    assertEquals(names, foo.names);
+  }
+
+  static class Foo {
+    @Inject List<String> names;
+  }
+
+  /**
+   * Although we may not have intended to support this behaviour, this test
+   * passes under Guice 1.0. The workaround is to add an explicit binding for
+   * the parameterized type. See {@link #testExplicitBindingOfGenericType()}.
+   */
+  public void testImplicitBindingOfGenericType() {
+    Parameterized<String> parameterized
+        = Guice.createInjector().getInstance(Key.get(new TypeLiteral<Parameterized<String>>() {}));
+    assertNotNull(parameterized);
+  }
+
+  public void testExplicitBindingOfGenericType() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Key.get(new TypeLiteral<Parameterized<String>>() {}))
+            .to((Class) Parameterized.class);
+      }
+    });
+
+    Parameterized<String> parameterized
+        = injector.getInstance(Key.get(new TypeLiteral<Parameterized<String>>() { }));
+    assertNotNull(parameterized);
+  }
+
+  static class Parameterized<T> {
+    @Inject
+    Parameterized() { }
+  }
+
+  public void testInjectingParameterizedDependenciesForImplicitBinding() {
+    assertParameterizedDepsInjected(new Key<ParameterizedDeps<String, Integer>>() {},
+        Modules.EMPTY_MODULE);
+  }
+
+  public void testInjectingParameterizedDependenciesForBindingTarget() {
+    final TypeLiteral<ParameterizedDeps<String, Integer>> type
+        = new TypeLiteral<ParameterizedDeps<String, Integer>>() {};
+
+    assertParameterizedDepsInjected(Key.get(Object.class), new AbstractModule() {
+      protected void configure() {
+        bind(Object.class).to(type);
+      }
+    });
+  }
+
+  public void testInjectingParameterizedDependenciesForBindingSource() {
+    final TypeLiteral<ParameterizedDeps<String, Integer>> type
+        = new TypeLiteral<ParameterizedDeps<String, Integer>>() {};
+
+    assertParameterizedDepsInjected(Key.get(type), new AbstractModule() {
+      protected void configure() {
+        bind(type);
+      }
+    });
+  }
+
+  public void testBindingToSubtype() {
+    final TypeLiteral<ParameterizedDeps<String, Integer>> type
+        = new TypeLiteral<ParameterizedDeps<String, Integer>>() {};
+
+    assertParameterizedDepsInjected(Key.get(type), new AbstractModule() {
+      protected void configure() {
+        bind(type).to(new TypeLiteral<SubParameterizedDeps<String, Long, Integer>>() {});
+      }
+    });
+  }
+
+  public void testBindingSubtype() {
+    final TypeLiteral<SubParameterizedDeps<String, Long, Integer>> type
+        = new TypeLiteral<SubParameterizedDeps<String, Long, Integer>>() {};
+
+    assertParameterizedDepsInjected(Key.get(type), new AbstractModule() {
+      protected void configure() {
+        bind(type);
+      }
+    });
+  }
+
+  @SuppressWarnings("unchecked")
+  public void assertParameterizedDepsInjected(Key<?> key, Module bindingModule) {
+    Module bindDataModule = new AbstractModule() {
+      protected void configure() {}
+      @Provides Map<String, Integer> provideMap() {
+        return ImmutableMap.of("one", 1, "two", 2);
+      }
+      @Provides Set<String> provideSet(Map<String, Integer> map) {
+        return map.keySet();
+      }
+      @Provides Collection<Integer> provideCollection(Map<String, Integer> map) {
+        return map.values();
+      }
+    };
+
+    Injector injector = Guice.createInjector(bindDataModule, bindingModule);
+    ParameterizedDeps<String, Integer> parameterizedDeps
+        = (ParameterizedDeps<String, Integer>) injector.getInstance(key);
+    assertEquals(ImmutableMap.of("one", 1, "two", 2), parameterizedDeps.map);
+    assertEquals(ImmutableSet.of("one", "two"), parameterizedDeps.keys);
+    assertEquals(ImmutableSet.of(1, 2), ImmutableSet.copyOf(parameterizedDeps.values));
+  }
+
+  static class SubParameterizedDeps<A, B, C> extends ParameterizedDeps<A, C> {
+    @Inject SubParameterizedDeps(Set<A> keys) {
+      super(keys);
+    }
+  }
+
+  static class ParameterizedDeps<K, V> {
+    @Inject private Map<K, V> map;
+    private Set<K> keys;
+    private Collection<V> values;
+
+    @Inject ParameterizedDeps(Set<K> keys) {
+      this.keys = keys;
+    }
+
+    @Inject void method(Collection<V> values) {
+      this.values = values;
+    }
+  }
+
+  public void testImmediateTypeVariablesAreInjected() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toInstance("tee");
+      }
+    });
+    InjectsT<String> injectsT = injector.getInstance(new Key<InjectsT<String>>() {});
+    assertEquals("tee", injectsT.t);
+  }
+
+  static class InjectsT<T> {
+    @Inject T t;
+  }
+}
diff --git a/core/test/com/google/inject/ImplicitBindingTest.java b/core/test/com/google/inject/ImplicitBindingTest.java
new file mode 100644
index 0000000..eb47e49
--- /dev/null
+++ b/core/test/com/google/inject/ImplicitBindingTest.java
@@ -0,0 +1,395 @@
+/**
+ * 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 com.google.inject;
+
+import com.google.common.collect.Iterables;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Message;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ImplicitBindingTest extends TestCase {
+
+  public void testCircularDependency() throws CreationException {
+    Injector injector = Guice.createInjector();
+    Foo foo = injector.getInstance(Foo.class);
+    assertSame(foo, foo.bar.foo);
+  }
+
+  static class Foo {
+    @Inject Bar bar;
+  }
+
+  static class Bar {
+    final Foo foo;
+    @Inject
+    public Bar(Foo foo) {
+      this.foo = foo;
+    }
+  }
+
+  public void testDefaultImplementation() {
+    Injector injector = Guice.createInjector();
+    I i = injector.getInstance(I.class);
+    i.go();
+  }
+
+  @ImplementedBy(IImpl.class)
+  interface I {
+    void go();
+  }
+
+  static class IImpl implements I {
+    public void go() {}
+  }
+
+  static class AlternateImpl implements I {
+    public void go() {}
+  }
+
+  public void testDefaultProvider() {
+    Injector injector = Guice.createInjector();
+    Provided provided = injector.getInstance(Provided.class);
+    provided.go();
+  }
+
+  public void testBindingOverridesImplementedBy() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(I.class).to(AlternateImpl.class);
+      }
+    });
+    assertEquals(AlternateImpl.class, injector.getInstance(I.class).getClass());
+  }
+
+  @ProvidedBy(ProvidedProvider.class)
+  interface Provided {
+    void go();
+  }
+
+  public void testNoImplicitBindingIsCreatedForAnnotatedKeys() {
+    try {
+      Guice.createInjector().getInstance(Key.get(I.class, Names.named("i")));
+      fail();
+    } catch (ConfigurationException expected) {
+      Asserts.assertContains(expected.getMessage(),
+          "1) No implementation for " + I.class.getName(),
+          "annotated with @" + Named.class.getName() + "(value=i) was bound.",
+          "while locating " + I.class.getName(),
+          " annotated with @" + Named.class.getName() + "(value=i)");
+    }
+  }
+
+  static class ProvidedProvider implements Provider<Provided> {
+    public Provided get() {
+      return new Provided() {
+        public void go() {}
+      };
+    }
+  }
+
+  /**
+   * When we're building the binding for A, we temporarily insert that binding to support circular
+   * dependencies. And so we can successfully create a binding for B. But later, when the binding
+   * for A ultimately fails, we need to clean up the dependent binding for B.
+   * 
+   * The test loops through linked bindings & bindings with constructor & member injections,
+   * to make sure that all are cleaned up and traversed.  It also makes sure we don't touch
+   * explicit bindings.
+   */
+  public void testCircularJitBindingsLeaveNoResidue() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Valid.class);
+        bind(Valid2.class);
+      }
+    });
+    
+    // Capture good bindings.
+    Binding v1 = injector.getBinding(Valid.class);
+    Binding v2 = injector.getBinding(Valid2.class);
+    Binding jv1 = injector.getBinding(JitValid.class);
+    Binding jv2 = injector.getBinding(JitValid2.class);
+
+    // Then validate that a whole series of invalid bindings are erased.
+    assertFailure(injector, Invalid.class);
+    assertFailure(injector, InvalidLinked.class);
+    assertFailure(injector, InvalidLinkedImpl.class);
+    assertFailure(injector, InvalidLinked2.class);
+    assertFailure(injector, InvalidLinked2Impl.class);
+    assertFailure(injector, InvalidProvidedBy.class);
+    assertFailure(injector, InvalidProvidedByProvider.class);
+    assertFailure(injector, InvalidProvidedBy2.class);
+    assertFailure(injector, InvalidProvidedBy2Provider.class);
+    assertFailure(injector, Invalid2.class);
+    
+    // Validate we didn't do anything to the valid explicit bindings.
+    assertSame(v1, injector.getBinding(Valid.class));
+    assertSame(v2, injector.getBinding(Valid2.class));
+    
+    // Validate that we didn't erase the valid JIT bindings
+    assertSame(jv1, injector.getBinding(JitValid.class));
+    assertSame(jv2, injector.getBinding(JitValid2.class));
+  }
+  
+  @SuppressWarnings("unchecked")
+  private void assertFailure(Injector injector, Class clazz) {
+    try {
+      injector.getBinding(clazz);
+      fail("Shouldn't have been able to get binding of: " + clazz);
+    } catch(ConfigurationException expected) {
+      Message msg = Iterables.getOnlyElement(expected.getErrorMessages());
+      assertEquals("No implementation for " + InvalidInterface.class.getName() + " was bound.",
+          msg.getMessage());
+      List<Object> sources = msg.getSources();
+      // Assert that the first item in the sources if the key for the class we're looking up,
+      // ensuring that each lookup is "new".
+      assertEquals(Key.get(clazz).toString(), sources.get(0).toString());
+      // Assert that the last item in each lookup contains the InvalidInterface class
+      Asserts.assertContains(sources.get(sources.size()-1).toString(),
+          Key.get(InvalidInterface.class).toString());
+    }
+  }
+
+  static class Invalid {
+    @Inject Valid a;
+    @Inject JitValid b;    
+    @Inject InvalidProvidedBy c; 
+    @Inject Invalid(InvalidLinked a) {}    
+    @Inject void foo(InvalidInterface a) {}
+    
+  }
+
+  @ImplementedBy(InvalidLinkedImpl.class)
+  static interface InvalidLinked {}
+  static class InvalidLinkedImpl implements InvalidLinked {
+    @Inject InvalidLinked2 a;
+  }
+  
+  @ImplementedBy(InvalidLinked2Impl.class)
+  static interface InvalidLinked2 {}
+  static class InvalidLinked2Impl implements InvalidLinked2 {
+    @Inject InvalidLinked2Impl(Invalid2 a) {}
+  }
+  
+  @ProvidedBy(InvalidProvidedByProvider.class)
+  static interface InvalidProvidedBy {}
+  static class InvalidProvidedByProvider implements Provider<InvalidProvidedBy> {
+    @Inject InvalidProvidedBy2 a;
+    public InvalidProvidedBy get() {
+      return null;
+    }
+  }
+  
+  @ProvidedBy(InvalidProvidedBy2Provider.class)
+  static interface InvalidProvidedBy2 {}
+  static class InvalidProvidedBy2Provider implements Provider<InvalidProvidedBy2> {
+    @Inject Invalid2 a;
+    public InvalidProvidedBy2 get() {
+      return null;
+    }
+  }  
+  
+  static class Invalid2 {
+    @Inject Invalid a;
+  }
+
+  interface InvalidInterface {}
+  
+  static class Valid { @Inject Valid2 a; }
+  static class Valid2 {}
+  
+  static class JitValid { @Inject JitValid2 a; }
+  static class JitValid2 {}
+  
+  /**
+   * Regression test for https://github.com/google/guice/issues/319
+   * 
+   * The bug is that a class that asks for a provider for itself during injection time, 
+   * where any one of the other types required to fulfill the object creation was bound 
+   * in a child constructor, explodes when the injected Provider is called.
+   * 
+   * It works just fine when the other types are bound in a main injector.
+   */  
+  public void testInstancesRequestingProvidersForThemselvesWithChildInjectors() {       
+    final Module testModule = new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class)
+          .toProvider(TestStringProvider.class);
+      }            
+    };    
+    
+    // Verify it works when the type is setup in the parent.
+    Injector parentSetupRootInjector = Guice.createInjector(testModule);
+    Injector parentSetupChildInjector = parentSetupRootInjector.createChildInjector();
+    assertEquals(TestStringProvider.TEST_VALUE, 
+        parentSetupChildInjector.getInstance(
+            RequiresProviderForSelfWithOtherType.class).getValue());
+        
+    // Verify it works when the type is setup in the child, not the parent.
+    // If it still occurs, the bug will explode here.
+    Injector childSetupRootInjector = Guice.createInjector();
+    Injector childSetupChildInjector = childSetupRootInjector.createChildInjector(testModule);      
+    assertEquals(TestStringProvider.TEST_VALUE, 
+        childSetupChildInjector.getInstance(
+            RequiresProviderForSelfWithOtherType.class).getValue());
+  }
+  
+  static class TestStringProvider implements Provider<String> {
+    static final String TEST_VALUE = "This is to verify it all works";
+    
+    public String get() {
+      return TEST_VALUE;
+    }    
+  }    
+  
+  static class RequiresProviderForSelfWithOtherType {
+    private final Provider<RequiresProviderForSelfWithOtherType> selfProvider;
+    private final String providedStringValue;
+    
+    @Inject    
+    RequiresProviderForSelfWithOtherType(
+        String providedStringValue,
+        Provider<RequiresProviderForSelfWithOtherType> selfProvider
+        ) {
+      this.providedStringValue = providedStringValue;
+      this.selfProvider = selfProvider;      
+    }
+    
+    public String getValue() {
+      // Attempt to get another instance of ourself. This pattern
+      // is possible for recursive processing. 
+      selfProvider.get();
+      
+      return providedStringValue;
+    }
+  }
+
+  /**
+   * Ensure that when we cleanup failed JIT bindings, we don't break.
+   * The test here requires a sequence of JIT bindings:
+   *   A-> B 
+   *   B -> C, A
+   *   C -> A, D
+   *   D not JITable
+   * The problem was that C cleaned up A's binding and then handed control back to B,
+   * which tried to continue processing A.. but A was removed from the jitBindings Map,
+   * so it attempts to create a new JIT binding for A, but we haven't yet finished
+   * constructing the first JIT binding for A, so we get a recursive
+   * computation exception from ComputingConcurrentHashMap.
+   * 
+   * We also throw in a valid JIT binding, E, to guarantee that if
+   * something fails in this flow, it can be recreated later if it's
+   * not from a failed sequence.
+   */
+  public void testRecursiveJitBindingsCleanupCorrectly() throws Exception {
+    Injector injector = Guice.createInjector();
+    try {
+      injector.getInstance(A.class);
+      fail("Expected failure");
+    } catch(ConfigurationException expected) {
+      Message msg = Iterables.getOnlyElement(expected.getErrorMessages());
+      Asserts.assertContains(msg.getMessage(),
+          "Could not find a suitable constructor in " + D.class.getName());
+    }
+    // Assert that we've removed all the bindings.
+    assertNull(injector.getExistingBinding(Key.get(A.class)));
+    assertNull(injector.getExistingBinding(Key.get(B.class)));
+    assertNull(injector.getExistingBinding(Key.get(C.class)));
+    assertNull(injector.getExistingBinding(Key.get(D.class)));
+    
+    // Confirm that we didn't prevent 'E' from working.
+    assertNotNull(injector.getBinding(Key.get(E.class)));
+  }
+
+  static class A {
+    @Inject public A(B b) {}
+  }
+
+  static class B {
+    @Inject public B(C c, A a) {}
+  }
+
+  static class C {
+    @Inject public C(A a, D d, E e) {}
+  }
+
+  static class D {
+    public D(int i) {}
+  }
+  
+  // Valid JITable binding
+  static class E { }
+
+  public void testProvidedByNonEmptyEnum() {
+    NonEmptyEnum cardSuit = Guice.createInjector().getInstance(NonEmptyEnum.class);
+
+    assertEquals(NonEmptyEnum.HEARTS, cardSuit);
+  }
+
+  public void testProvidedByEmptyEnum() {
+    EmptyEnum emptyEnumValue = Guice.createInjector().getInstance(EmptyEnum.class);
+    assertNull(emptyEnumValue);
+  }
+
+  @ProvidedBy(NonEmptyEnumProvider.class)
+  enum NonEmptyEnum { HEARTS, DIAMONDS, CLUBS, SPADES }
+
+  static final class NonEmptyEnumProvider implements Provider<NonEmptyEnum> {
+    @Override
+    public NonEmptyEnum get() {
+      return NonEmptyEnum.HEARTS;
+    }
+  }
+
+  @ProvidedBy(EmptyEnumProvider.class)
+  enum EmptyEnum {}
+
+  static final class EmptyEnumProvider implements Provider<EmptyEnum> {
+    @Override
+    public EmptyEnum get() {
+      return null;
+    }
+  }
+
+  // An enum cannot be implemented by anything, so it should not be possible to have a successful
+  // binding when the enum is annotated with @ImplementedBy.
+  public void testImplementedByEnum() {
+    Injector injector = Guice.createInjector();
+    try {
+      injector.getInstance(EnumWithImplementedBy.class);
+      fail("Expected failure");
+    } catch(ConfigurationException expected) {
+      Message msg = Iterables.getOnlyElement(expected.getErrorMessages());
+      Asserts.assertContains(msg.getMessage(),
+          "No implementation for " + EnumWithImplementedBy.class.getName() + " was bound.");
+    }
+  }
+
+  @ImplementedBy(EnumWithImplementedByEnum.class)
+  enum EnumWithImplementedBy {}
+  private static class EnumWithImplementedByEnum {}
+}
diff --git a/core/test/com/google/inject/InjectorTest.java b/core/test/com/google/inject/InjectorTest.java
new file mode 100644
index 0000000..a71eb18
--- /dev/null
+++ b/core/test/com/google/inject/InjectorTest.java
@@ -0,0 +1,413 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.assertNotSerializable;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+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.atomic.AtomicReference;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+
+public class InjectorTest extends TestCase {
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface Other {}
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface S {}
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface I {}
+
+  public void testToStringDoesNotInfinitelyRecurse() {
+    Injector injector = Guice.createInjector(Stage.TOOL);
+    injector.toString();
+    injector.getBinding(Injector.class).toString();
+  }
+
+  public void testProviderMethods() throws CreationException {
+    final SampleSingleton singleton = new SampleSingleton();
+    final SampleSingleton other = new SampleSingleton();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(SampleSingleton.class).toInstance(singleton);
+        bind(SampleSingleton.class)
+            .annotatedWith(Other.class)
+            .toInstance(other);
+      }
+    });
+
+    assertSame(singleton,
+        injector.getInstance(Key.get(SampleSingleton.class)));
+    assertSame(singleton, injector.getInstance(SampleSingleton.class));
+
+    assertSame(other,
+        injector.getInstance(Key.get(SampleSingleton.class, Other.class)));
+  }
+
+  static class SampleSingleton {}
+
+  public void testInjection() throws CreationException {
+    Injector injector = createFooInjector();
+    Foo foo = injector.getInstance(Foo.class);
+
+    assertEquals("test", foo.s);
+    assertEquals("test", foo.bar.getTee().getS());
+    assertSame(foo.bar, foo.copy);
+    assertEquals(5, foo.i);
+    assertEquals(5, foo.bar.getI());
+
+    // Test circular dependency.
+    assertSame(foo.bar, foo.bar.getTee().getBar());
+  }
+
+  private Injector createFooInjector() throws CreationException {
+    return Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Bar.class).to(BarImpl.class);
+        bind(Tee.class).to(TeeImpl.class);
+        bindConstant().annotatedWith(S.class).to("test");
+        bindConstant().annotatedWith(I.class).to(5);
+      }
+    });
+  }
+
+  public void testGetInstance() throws CreationException {
+    Injector injector = createFooInjector();
+
+    Bar bar = injector.getInstance(Key.get(Bar.class));
+    assertEquals("test", bar.getTee().getS());
+    assertEquals(5, bar.getI());
+  }
+
+  public void testIntAndIntegerAreInterchangeable()
+      throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindConstant().annotatedWith(I.class).to(5);
+      }
+    });
+
+    IntegerWrapper iw = injector.getInstance(IntegerWrapper.class);
+    assertEquals(5, (int) iw.i);
+  }
+
+  public void testInjectorApiIsNotSerializable() throws IOException {
+    Injector injector = Guice.createInjector();
+    assertNotSerializable(injector);
+    assertNotSerializable(injector.getProvider(String.class));
+    assertNotSerializable(injector.getBinding(String.class));
+    for (Binding<?> binding : injector.getBindings().values()) {
+      assertNotSerializable(binding);
+    }
+  }
+
+  static class IntegerWrapper {
+    @Inject @I Integer i;
+  }
+
+  static class Foo {
+
+    @Inject Bar bar;
+    @Inject Bar copy;
+
+    @Inject @S String s;
+
+    int i;
+
+    @Inject
+    void setI(@I int i) {
+      this.i = i;
+    }
+  }
+
+  interface Bar {
+
+    Tee getTee();
+    int getI();
+  }
+
+  @Singleton
+  static class BarImpl implements Bar {
+
+    @Inject @I int i;
+
+    Tee tee;
+
+    @Inject
+    void initialize(Tee tee) {
+      this.tee = tee;
+    }
+
+    public Tee getTee() {
+      return tee;
+    }
+
+    public int getI() {
+      return i;
+    }
+  }
+
+  interface Tee {
+
+    String getS();
+    Bar getBar();
+  }
+
+  static class TeeImpl implements Tee {
+
+    final String s;
+    @Inject Bar bar;
+
+    @Inject
+    TeeImpl(@S String s) {
+      this.s = s;
+    }
+
+    public String getS() {
+      return s;
+    }
+
+    public Bar getBar() {
+      return bar;
+    }
+  }
+
+  public void testInjectStatics() throws CreationException {
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindConstant().annotatedWith(S.class).to("test");
+        bindConstant().annotatedWith(I.class).to(5);
+        requestStaticInjection(Static.class);
+      }
+    });
+
+    assertEquals("test", Static.s);
+    assertEquals(5, Static.i);
+  }
+
+  public void testInjectStaticInterface() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          requestStaticInjection(Interface.class);
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      Asserts.assertContains(
+          ce.getMessage(),
+          "1) " + Interface.class.getName()
+              + " is an interface, but interfaces have no static injection points.",
+          "at " + InjectorTest.class.getName(),
+          "configure");
+    }
+  }
+
+  private static interface Interface {}
+
+  static class Static {
+
+    @Inject @I static int i;
+
+    static String s;
+
+    @Inject static void setS(@S String s) {
+      Static.s = s;
+    }
+  }
+
+  public void testPrivateInjection() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toInstance("foo");
+        bind(int.class).toInstance(5);
+      }
+    });
+
+    Private p = injector.getInstance(Private.class);
+    assertEquals("foo", p.fromConstructor);
+    assertEquals(5, p.fromMethod);
+  }
+
+  static class Private {
+    String fromConstructor;
+    int fromMethod;
+
+    @Inject
+    private Private(String fromConstructor) {
+      this.fromConstructor = fromConstructor;
+    }
+
+    @Inject
+    private void setInt(int i) {
+      this.fromMethod = i;
+    }
+  }
+
+  public void testProtectedInjection() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toInstance("foo");
+        bind(int.class).toInstance(5);
+      }
+    });
+
+    Protected p = injector.getInstance(Protected.class);
+    assertEquals("foo", p.fromConstructor);
+    assertEquals(5, p.fromMethod);
+  }
+
+  static class Protected {
+    String fromConstructor;
+    int fromMethod;
+
+    @Inject
+    protected Protected(String fromConstructor) {
+      this.fromConstructor = fromConstructor;
+    }
+
+    @Inject
+    protected void setInt(int i) {
+      this.fromMethod = i;
+    }
+  }
+
+  public void testInstanceInjectionHappensAfterFactoriesAreSetUp() {
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Object.class).toInstance(new Object() {
+          @Inject Runnable r;
+        });
+
+        bind(Runnable.class).to(MyRunnable.class);
+      }
+    });
+  }
+
+  public void testSubtypeNotProvided() {
+    try {
+      Guice.createInjector().getInstance(Money.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          Tree.class.getName() + " doesn't provide instances of " + Money.class.getName(),
+          "while locating ", Tree.class.getName(),
+          "while locating ", Money.class.getName());
+    }
+  }
+
+  public void testNotASubtype() {
+    try {
+      Guice.createInjector().getInstance(PineTree.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          Tree.class.getName() + " doesn't extend " + PineTree.class.getName(),
+          "while locating ", PineTree.class.getName());
+    }
+  }
+
+  public void testRecursiveImplementationType() {
+    try {
+      Guice.createInjector().getInstance(SeaHorse.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "@ImplementedBy points to the same class it annotates.",
+          "while locating ", SeaHorse.class.getName());
+    }
+  }
+
+  public void testRecursiveProviderType() {
+    try {
+      Guice.createInjector().getInstance(Chicken.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "@ProvidedBy points to the same class it annotates",
+          "while locating ", Chicken.class.getName());
+    }
+  }
+
+  static class MyRunnable implements Runnable {
+   public void run() {}
+  }
+
+  @ProvidedBy(Tree.class)
+  static class Money {}
+
+  static class Tree implements Provider<Object> {
+    public Object get() {
+      return "Money doesn't grow on trees";
+    }
+  }
+
+  @ImplementedBy(Tree.class)
+  static class PineTree extends Tree {}
+
+  @ImplementedBy(SeaHorse.class)
+  static class SeaHorse {}
+
+  @ProvidedBy(Chicken.class)
+  static class Chicken implements Provider<Chicken> {
+    public Chicken get() {
+      return this;
+    }
+  }
+
+  public void testJitBindingFromAnotherThreadDuringInjection() {
+    final ExecutorService executorService = Executors.newSingleThreadExecutor();
+    final AtomicReference<JustInTime> got = new AtomicReference<JustInTime>();
+
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        requestInjection(new Object() {
+          @Inject void initialize(final Injector injector)
+              throws ExecutionException, InterruptedException {
+            Future<JustInTime> future = executorService.submit(new Callable<JustInTime>() {
+              public JustInTime call() throws Exception {
+                return injector.getInstance(JustInTime.class);
+              }
+            });
+            got.set(future.get());
+          }
+        });
+      }
+    });
+
+    assertNotNull(got.get());
+  }
+
+  static class JustInTime {}
+}
diff --git a/core/test/com/google/inject/IntegrationTest.java b/core/test/com/google/inject/IntegrationTest.java
new file mode 100644
index 0000000..ceff0ad
--- /dev/null
+++ b/core/test/com/google/inject/IntegrationTest.java
@@ -0,0 +1,69 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.matcher.Matchers.any;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class IntegrationTest extends TestCase {
+
+  public void testIntegration() throws CreationException {
+    final CountingInterceptor counter = new CountingInterceptor();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class);
+        bindInterceptor(any(), any(), counter);
+      }
+    });
+
+    Foo foo = injector.getInstance(Key.get(Foo.class));
+    foo.foo();
+    assertTrue(foo.invoked);
+    assertEquals(1, counter.count);
+
+    foo = injector.getInstance(Foo.class);
+    foo.foo();
+    assertTrue(foo.invoked);
+    assertEquals(2, counter.count);
+  }
+
+  static class Foo {
+    boolean invoked;
+    public void foo() {
+      invoked = true;
+    }
+  }
+
+  static class CountingInterceptor implements MethodInterceptor {
+
+    int count;
+
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      count++;
+      return methodInvocation.proceed();
+    }
+  }
+
+}
diff --git a/core/test/com/google/inject/JitBindingsTest.java b/core/test/com/google/inject/JitBindingsTest.java
new file mode 100644
index 0000000..243c53e
--- /dev/null
+++ b/core/test/com/google/inject/JitBindingsTest.java
@@ -0,0 +1,731 @@
+/*
+ * Copyright (C) 2010 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.inject;
+
+import static com.google.common.collect.ImmutableSet.of;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING;
+import static com.google.inject.JitBindingsTest.GetBindingCheck.FAIL_ALL;
+
+import junit.framework.TestCase;
+
+import java.util.Set;
+
+/**
+ * Some tests for {@link Binder#requireExplicitBindings()}
+ * 
+ * @author sberlin@gmail.com (Sam Berlin)
+ */
+public class JitBindingsTest extends TestCase {
+  
+  private String jitFailed(Class<?> clazz) {
+    return jitFailed(TypeLiteral.get(clazz));
+  }
+  
+  private String jitFailed(TypeLiteral<?> clazz) {
+    return "Explicit bindings are required and " + clazz + " is not explicitly bound.";
+  }
+
+  private String jitInParentFailed(Class<?> clazz) {
+    return jitInParentFailed(TypeLiteral.get(clazz));
+  }
+
+  private String jitInParentFailed(TypeLiteral<?> clazz) {
+    return "Explicit bindings are required and " + clazz + " would be bound in a parent injector.";
+  }
+  
+  private String inChildMessage(Class<?> clazz) {
+    return "Unable to create binding for "
+        + clazz.getName()
+        + ". It was already configured on one or more child injectors or private modules";
+  }
+  
+  public void testLinkedBindingWorks() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class).to(FooImpl.class);
+      }
+    });
+    // Foo was explicitly bound
+    ensureWorks(injector, Foo.class);
+    // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
+    // It is OK to call getBinding for introspection, but an error to get the provider
+    // of the binding
+    ensureFails(injector, ALLOW_BINDING, FooImpl.class);
+  }
+  
+  public void testMoreBasicsWork() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class).to(FooImpl.class);
+        bind(Bar.class);
+        bind(FooBar.class);
+      }
+    });
+    // Foo, Bar & FooBar was explicitly bound    
+    ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
+    // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
+    // It is OK to call getBinding for introspection, but an error to get the provider
+    // of the binding    
+    ensureFails(injector, ALLOW_BINDING,  FooImpl.class);    
+  }
+  
+  public void testLinkedEagerSingleton() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class).to(FooImpl.class).asEagerSingleton();
+      }
+    });
+    // Foo was explicitly bound
+    ensureWorks(injector, Foo.class);
+    // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
+    // It is OK to call getBinding for introspection, but an error to get the provider
+    // of the binding
+    ensureFails(injector, ALLOW_BINDING, FooImpl.class);
+  }
+  
+  public void testBasicsWithEagerSingleton() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class).to(FooImpl.class).asEagerSingleton();
+        bind(Bar.class);
+        bind(FooBar.class);
+      }
+    });
+    // Foo, Bar & FooBar was explicitly bound    
+    ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
+    // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
+    // It is OK to call getBinding for introspection, but an error to get the provider
+    // of the binding    
+    ensureFails(injector, ALLOW_BINDING,  FooImpl.class);    
+  }  
+  
+  public void testLinkedToScoped() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder.requireExplicitBindings();
+        bind(Foo.class).to(ScopedFooImpl.class);
+      }
+    });
+    // Foo was explicitly bound
+    ensureWorks(injector, Foo.class);
+    // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
+    // It is OK to call getBinding for introspection, but an error to get the provider
+    // of the binding
+    ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class);    
+  }
+  
+  public void testBasicsWithScoped() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class).to(ScopedFooImpl.class);
+        bind(Bar.class);
+        bind(FooBar.class);
+      }
+    });
+    // Foo, Bar & FooBar was explicitly bound    
+    ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
+    // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
+    // It is OK to call getBinding for introspection, but an error to get the provider
+    // of the binding    
+    ensureFails(injector, ALLOW_BINDING,  ScopedFooImpl.class);   
+  }
+  
+  public void testFailsIfInjectingScopedDirectlyWhenItIsntBound() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExplicitBindings();
+          bind(Foo.class).to(ScopedFooImpl.class);
+          bind(WantsScopedFooImpl.class);
+        }
+      });
+      fail();
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(), jitFailed(ScopedFooImpl.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+  
+  public void testLinkedProviderBindingWorks() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class).toProvider(FooProvider.class);
+      }
+    });
+    // Foo was explicitly bound
+    ensureWorks(injector, Foo.class);
+    // FooImpl was not bound at all (even implicitly), it is an error
+    // to call getInstance, getProvider, or getBinding.
+    ensureFails(injector, FAIL_ALL, FooImpl.class);
+  }
+  
+  public void testJitGetFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+         binder().requireExplicitBindings(); 
+        }
+      }).getInstance(Bar.class);
+      fail("should have failed");
+    } catch(ConfigurationException expected) {
+      assertContains(expected.getMessage(), jitFailed(Bar.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+  
+  public void testJitInjectionFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExplicitBindings();
+          bind(Foo.class).to(FooImpl.class);
+          bind(FooBar.class);
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), jitFailed(Bar.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+
+  public void testJitProviderGetFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExplicitBindings(); 
+        }
+      }).getProvider(Bar.class);
+      fail("should have failed");
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), jitFailed(Bar.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+
+  public void testJitProviderInjectionFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExplicitBindings();
+          bind(Foo.class).to(FooImpl.class);
+          bind(ProviderFooBar.class);
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), jitFailed(Bar.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+  
+  public void testImplementedBy() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(ImplBy.class);
+      }
+    });
+    ensureWorks(injector, ImplBy.class);
+    ensureFails(injector, ALLOW_BINDING, ImplByImpl.class);
+  }
+  
+  public void testImplementedBySomethingThatIsAnnotated() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(ImplByScoped.class);
+      }
+    });
+    ensureWorks(injector, ImplByScoped.class);
+    ensureFails(injector, ALLOW_BINDING, ImplByScopedImpl.class);    
+  }
+  
+  public void testProvidedBy() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(ProvBy.class);
+      }
+    });
+    ensureWorks(injector, ProvBy.class);
+    ensureFails(injector, ALLOW_BINDING, ProvByProvider.class);
+  }
+  
+  public void testProviderMethods() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        binder().requireExplicitBindings();
+      }
+      @SuppressWarnings("unused") @Provides Foo foo() { return new FooImpl(); }
+    });
+    ensureWorks(injector, Foo.class);
+  }
+  
+  public void testChildInjectorInheritsOption() {
+    Injector parent = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Bar.class);
+      }
+    });
+    ensureWorks(parent, Bar.class);
+    ensureFails(parent, FAIL_ALL, FooImpl.class, FooBar.class, Foo.class);
+    
+    try {
+      parent.createChildInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(FooBar.class);
+        }
+      });
+      fail("should have failed");
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(), jitFailed(Foo.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+    
+    Injector child = parent.createChildInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Foo.class).to(FooImpl.class);
+      }
+    });
+    ensureWorks(child, Foo.class, Bar.class);
+    ensureFails(child, ALLOW_BINDING, FooImpl.class);
+    ensureInChild(parent, FooImpl.class, Foo.class);
+    // TODO(sameb): FooBar may or may not be in a child injector, depending on if GC has run.
+    // We should fix failed child injectors to remove their contents from the parent blacklist
+    // immediately, rather than waiting on GC to do it.
+    // FooBar was succesfully inserted into the child injector (and parent blacklist), but then
+    // JIT bindings it depended on failed, making the child injector invalid.
+
+    Injector grandchild = child.createChildInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(FooBar.class);
+      }
+    });
+    ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class);
+    ensureFails(grandchild, ALLOW_BINDING, FooImpl.class);
+    ensureFails(child, ALLOW_BINDING, FooImpl.class);
+    ensureInChild(parent, FooImpl.class, FooBar.class, Foo.class);
+  }
+  
+  public void testChildInjectorAddsOption() {
+    Injector parent = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Bar.class);
+      }
+    });
+    int totalParentBindings = parent.getAllBindings().size();
+    
+    try {
+      parent.createChildInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExplicitBindings();
+          bind(FooBar.class);
+        }
+      });
+      fail("should have failed");
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(), jitFailed(Foo.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+    assertEquals(totalParentBindings, parent.getAllBindings().size());
+    
+    Injector child = parent.createChildInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class).to(FooImpl.class);
+        bind(FooImpl.class);
+      }
+    });
+    assertEquals(totalParentBindings, parent.getAllBindings().size());
+    ensureWorks(child, Foo.class, Bar.class);
+    
+    Injector grandchild = child.createChildInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(FooBar.class);
+      }
+    });
+    assertEquals(totalParentBindings, parent.getAllBindings().size());    
+    ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class);
+    
+    // Make sure siblings of children don't inherit each others settings...
+    // a new child should be able to get FooImpl.
+    child = parent.createChildInjector();
+    ensureWorks(child, FooImpl.class);
+  }
+
+  public void testPrivateModulesInheritOptions() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          binder().requireExplicitBindings();
+          bind(Foo.class).to(FooImpl.class);
+  
+          install(new PrivateModule() {
+            public void configure() {
+              bind(FooBar.class);
+              expose(FooBar.class);
+            }
+          });
+        }
+      });
+      fail("should have failed");
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(), jitFailed(Bar.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+    
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        binder().requireExplicitBindings();
+
+        install(new PrivateModule() {
+          public void configure() {
+            bind(Foo.class).to(FooImpl.class);
+            expose(Foo.class);
+          }
+        });
+      }
+    });
+    ensureInChild(injector, FooImpl.class);
+  }
+  
+  public void testPrivateModuleAddsOption() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(Foo.class).to(FooImpl.class);
+  
+          // Fails because FooBar is in the private module,
+          // and it wants Bar, but Bar would be JIT.
+          install(new PrivateModule() {
+            public void configure() {
+              binder().requireExplicitBindings();
+              bind(FooBar.class);
+              expose(FooBar.class);
+            }
+          });
+        }
+      });
+      fail("should have failed");
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(), jitFailed(Bar.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+
+  public void testPrivateModuleSiblingsDontShareOption() {
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class).to(FooImpl.class);
+
+        install(new PrivateModule() {
+          public void configure() {
+            binder().requireExplicitBindings();
+          }
+        });
+
+        // This works, even though Bar is JIT,
+        // because the requireExplicitBindings isn't shared
+        // between sibling private modules.
+        install(new PrivateModule() {
+          public void configure() {
+            bind(FooBar.class);
+            expose(FooBar.class);
+          }
+        });
+      }
+    });
+  }  
+
+  public void testTypeLiteralsCanBeInjected() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          binder().requireExplicitBindings();
+          bind(new TypeLiteral<WantsTypeLiterals<String>>() {});
+          bind(new TypeLiteral<Set<String>>() {}).toInstance(of("bar"));
+        }
+      });
+
+    WantsTypeLiterals<String> foo = injector.getInstance(new Key<WantsTypeLiterals<String>>() {});
+    assertEquals(foo.literal.getRawType(), String.class);
+    assertEquals(of("bar"), foo.set);
+  }
+  
+  public void testMembersInjectorsCanBeInjected() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        binder().requireExplicitBindings();
+      }
+      
+      @Provides String data(MembersInjector<String> mi) {
+        String data = "foo";
+        mi.injectMembers(data);
+        return data;
+      }
+    });
+
+    String data = injector.getInstance(String.class);
+    assertEquals("foo", data);
+  }
+
+  public void testJitLinkedBindingInParentFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new PrivateModule() {
+            @Override
+            protected void configure() {
+              binder().requireExplicitBindings();
+              bind(Foo.class).to(FooImpl.class);
+            }
+          });
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), jitInParentFailed(FooImpl.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+
+  public void testJitProviderBindingInParentFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new PrivateModule() {
+            @Override
+            protected void configure() {
+              binder().requireExplicitBindings();
+              bind(Foo.class).toProvider(FooProvider.class);
+            }
+          });
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), jitInParentFailed(FooProvider.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+
+  public void testJitImplementedByBindingInParentFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new PrivateModule() {
+            @Override
+            protected void configure() {
+              binder().requireExplicitBindings();
+              bind(ImplBy.class);
+            }
+          });
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), jitInParentFailed(ImplByImpl.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+
+  public void testJitProvidedByBindingInParentFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new PrivateModule() {
+            @Override
+            protected void configure() {
+              binder().requireExplicitBindings();
+              bind(ProvBy.class);
+            }
+          });
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), jitInParentFailed(ProvByProvider.class));
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+
+  private void ensureWorks(Injector injector, Class<?>... classes) {
+    for(int i = 0; i < classes.length; i++) {
+      injector.getInstance(classes[i]);
+      injector.getProvider(classes[i]).get();
+      injector.getBinding(classes[i]).getProvider().get();
+    }
+  }
+  
+  enum GetBindingCheck { FAIL_ALL, ALLOW_BINDING, ALLOW_BINDING_PROVIDER }
+  private void ensureFails(Injector injector, GetBindingCheck getBinding, Class<?>... classes) {
+    for(int i = 0; i < classes.length; i++) {      
+      try { 
+        injector.getInstance(classes[i]);
+        fail("should have failed tring to retrieve class: " + classes[i]);
+      } catch(ConfigurationException expected) {
+        assertContains(expected.getMessage(), jitFailed(classes[i]));
+        assertEquals(1, expected.getErrorMessages().size());
+      }
+      
+      try { 
+        injector.getProvider(classes[i]);
+        fail("should have failed tring to retrieve class: " + classes[i]);
+      } catch(ConfigurationException expected) {
+        assertContains(expected.getMessage(), jitFailed(classes[i]));
+        assertEquals(1, expected.getErrorMessages().size());
+      }
+      
+      if (getBinding == GetBindingCheck.ALLOW_BINDING
+          || getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) {
+        Binding<?> binding = injector.getBinding(classes[i]);
+        try {
+          binding.getProvider();
+          if (getBinding != GetBindingCheck.ALLOW_BINDING_PROVIDER) {
+            fail("should have failed trying to retrieve class: " + classes[i]);
+          }
+        } catch(ConfigurationException expected) {
+          if (getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) {
+            throw expected;
+          }
+          assertContains(expected.getMessage(), jitFailed(classes[i]));
+          assertEquals(1, expected.getErrorMessages().size());
+        }
+      } else {
+        try {
+          injector.getBinding(classes[i]);
+          fail("should have failed tring to retrieve class: " + classes[i]);          
+        } catch(ConfigurationException expected) {
+          assertContains(expected.getMessage(), jitFailed(classes[i]));
+          assertEquals(1, expected.getErrorMessages().size());
+        }
+      }
+    }
+  }
+  
+  private void ensureInChild(Injector injector, Class<?>... classes) {
+    for(int i = 0; i < classes.length; i++) {      
+      try { 
+        injector.getInstance(classes[i]);
+        fail("should have failed tring to retrieve class: " + classes[i]);
+      } catch(ConfigurationException expected) {
+        assertContains(expected.getMessage(), inChildMessage(classes[i]));
+        assertEquals(1, expected.getErrorMessages().size());
+      }
+      
+      try { 
+        injector.getProvider(classes[i]);
+        fail("should have failed tring to retrieve class: " + classes[i]);
+      } catch(ConfigurationException expected) {
+        assertContains(expected.getMessage(), inChildMessage(classes[i]));
+        assertEquals(1, expected.getErrorMessages().size());
+      }
+      
+      try {
+        injector.getBinding(classes[i]);
+        fail("should have failed tring to retrieve class: " + classes[i]);          
+      } catch(ConfigurationException expected) {
+        assertContains(expected.getMessage(), inChildMessage(classes[i]));
+        assertEquals(1, expected.getErrorMessages().size());
+      }
+    }
+  }
+  
+  private static interface Foo {}
+  private static class FooImpl implements Foo {}
+  @Singleton private static class ScopedFooImpl implements Foo {}
+  private static class WantsScopedFooImpl {
+    @SuppressWarnings("unused") @Inject ScopedFooImpl scopedFoo;
+  }
+  private static class Bar {}
+  private static class FooBar {
+    @SuppressWarnings("unused") @Inject Foo foo;
+    @SuppressWarnings("unused") @Inject Bar bar;
+  }
+  private static class ProviderFooBar {
+    @SuppressWarnings("unused") @Inject Provider<Foo> foo;
+    @SuppressWarnings("unused") @Inject Provider<Bar> bar;
+  }
+  private static class FooProvider implements Provider<Foo> {
+    public Foo get() {
+      return new FooImpl();
+    }
+  }
+
+  @ImplementedBy(ImplByImpl.class)
+  private static interface ImplBy {}
+  private static class ImplByImpl implements ImplBy {}
+  
+  @ImplementedBy(ImplByScopedImpl.class)
+  private static interface ImplByScoped {}
+  @Singleton
+  private static class ImplByScopedImpl implements ImplByScoped {}  
+
+  @ProvidedBy(ProvByProvider.class)
+  private static interface ProvBy {}
+  private static class ProvByProvider implements Provider<ProvBy> {
+    public ProvBy get() {
+      return new ProvBy() {};
+    }
+  }
+  
+  private static class WantsTypeLiterals<T> {
+    TypeLiteral<T> literal;
+    Set<T> set;
+    
+    @Inject WantsTypeLiterals(TypeLiteral<T> literal, Set<T> set) {
+      this.literal = literal;
+      this.set = set;
+      
+    }
+  }
+}
diff --git a/core/test/com/google/inject/KeyTest.java b/core/test/com/google/inject/KeyTest.java
new file mode 100644
index 0000000..d9dd943
--- /dev/null
+++ b/core/test/com/google/inject/KeyTest.java
@@ -0,0 +1,321 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.assertEqualsBothWays;
+import static com.google.inject.Asserts.assertNotSerializable;
+import static com.google.inject.Asserts.awaitClear;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.util.Types;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class KeyTest extends TestCase {
+
+  public void foo(List<String> a, List<String> b) {}
+  public void bar(Provider<List<String>> a) {}
+  @Foo String baz;
+  List<? extends CharSequence> wildcardExtends;
+
+  public void testOfType() {
+    Key<Object> k = Key.get(Object.class, Foo.class);
+    Key<Integer> ki = k.ofType(Integer.class);
+    assertEquals(Integer.class, ki.getRawType());
+    assertEquals(Foo.class, ki.getAnnotationType());
+  }
+
+  public void testKeyEquality() {
+    Key<List<String>> a = new Key<List<String>>(Foo.class) {};
+    Key<List<String>> b = Key.get(new TypeLiteral<List<String>>() {}, Foo.class);
+    assertEqualsBothWays(a, b);
+  }
+
+  public void testProviderKey() throws NoSuchMethodException {
+    Key<?> actual = Key.get(getClass().getMethod("foo", List.class, List.class)
+        .getGenericParameterTypes()[0]).providerKey();
+    Key<?> expected = Key.get(getClass().getMethod("bar", Provider.class)
+        .getGenericParameterTypes()[0]);
+    assertEqualsBothWays(expected, actual);
+    assertEquals(expected.toString(), actual.toString());
+  }
+
+  public void testTypeEquality() throws Exception {
+    Method m = getClass().getMethod("foo", List.class, List.class);
+    Type[] types = m.getGenericParameterTypes();
+    assertEquals(types[0], types[1]);
+    Key<List<String>> k = new Key<List<String>>() {};
+    assertEquals(types[0], k.getTypeLiteral().getType());
+    assertFalse(types[0].equals(
+        new Key<List<Integer>>() {}.getTypeLiteral().getType()));
+  }
+
+  /**
+   * Key canonicalizes {@link int.class} to {@code Integer.class}, and
+   * won't expose wrapper types.
+   */
+  public void testPrimitivesAndWrappersAreEqual() {
+    Class[] primitives = new Class[] {
+        boolean.class, byte.class, short.class, int.class, long.class,
+        float.class, double.class, char.class, void.class
+    };
+    Class[] wrappers = new Class[] {
+        Boolean.class, Byte.class, Short.class, Integer.class, Long.class,
+        Float.class, Double.class, Character.class, Void.class
+    };
+
+    for (int t = 0; t < primitives.length; t++) {
+      @SuppressWarnings("unchecked")
+      Key primitiveKey = Key.get(primitives[t]);
+      @SuppressWarnings("unchecked")
+      Key wrapperKey = Key.get(wrappers[t]);
+
+      assertEquals(primitiveKey, wrapperKey);
+      assertEquals(wrappers[t], primitiveKey.getRawType());
+      assertEquals(wrappers[t], wrapperKey.getRawType());
+      assertEquals(wrappers[t], primitiveKey.getTypeLiteral().getType());
+      assertEquals(wrappers[t], wrapperKey.getTypeLiteral().getType());
+    }
+
+    Key<Integer> integerKey = Key.get(Integer.class);
+    Key<Integer> integerKey2 = Key.get(Integer.class, Named.class);
+    Key<Integer> integerKey3 = Key.get(Integer.class, Names.named("int"));
+
+    Class<Integer> intClassLiteral = int.class;
+    assertEquals(integerKey, Key.get(intClassLiteral));
+    assertEquals(integerKey2, Key.get(intClassLiteral, Named.class));
+    assertEquals(integerKey3, Key.get(intClassLiteral, Names.named("int")));
+
+    Type intType = int.class;
+    assertEquals(integerKey, Key.get(intType));
+    assertEquals(integerKey2, Key.get(intType, Named.class));
+    assertEquals(integerKey3, Key.get(intType, Names.named("int")));
+
+    TypeLiteral<Integer> intTypeLiteral = TypeLiteral.get(int.class);
+    assertEquals(integerKey, Key.get(intTypeLiteral));
+    assertEquals(integerKey2, Key.get(intTypeLiteral, Named.class));
+    assertEquals(integerKey3, Key.get(intTypeLiteral, Names.named("int")));
+  }
+
+  public void testSerialization() throws IOException, NoSuchFieldException {
+    assertNotSerializable(Key.get(B.class));
+    assertNotSerializable(Key.get(B.class, Names.named("bee")));
+    assertNotSerializable(Key.get(B.class, Named.class));
+    assertNotSerializable(Key.get(B[].class));
+    assertNotSerializable(Key.get(new TypeLiteral<Map<List<B>, B>>() {}));
+    assertNotSerializable(Key.get(new TypeLiteral<List<B[]>>() {}));
+    assertNotSerializable(Key.get(Types.listOf(Types.subtypeOf(CharSequence.class))));
+  }
+
+  public void testEqualityOfAnnotationTypesAndInstances() throws NoSuchFieldException {
+    Foo instance = getClass().getDeclaredField("baz").getAnnotation(Foo.class);
+    Key<String> keyWithInstance = Key.get(String.class, instance);
+    Key<String> keyWithLiteral = Key.get(String.class, Foo.class);
+    assertEqualsBothWays(keyWithInstance, keyWithLiteral);
+  }
+
+  public void testNonBindingAnnotationOnKey() {
+    try {
+      Key.get(String.class, Deprecated.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+      assertContains(expected.getMessage(), "java.lang.Deprecated is not a binding annotation. ",
+          "Please annotate it with @BindingAnnotation.");
+    }
+  }
+
+  public void testBindingAnnotationWithoutRuntimeRetention() {
+    try {
+      Key.get(String.class, Bar.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+      assertContains(expected.getMessage(), Bar.class.getName() + " is not retained at runtime.",
+          "Please annotate it with @Retention(RUNTIME).");
+    }
+  }
+
+  <T> void parameterizedWithVariable(List<T> typeWithVariables) {}
+
+  /** Test for issue 186 */
+  public void testCannotCreateKeysWithTypeVariables() throws NoSuchMethodException {
+    ParameterizedType listOfTType = (ParameterizedType) getClass().getDeclaredMethod(
+        "parameterizedWithVariable", List.class).getGenericParameterTypes()[0];
+
+    TypeLiteral<?> listOfT = TypeLiteral.get(listOfTType);
+    try {
+      Key.get(listOfT);
+      fail("Guice should not allow keys for java.util.List<T>");
+    } catch (ConfigurationException e) {
+      assertContains(e.getMessage(),
+          "java.util.List<T> cannot be used as a key; It is not fully specified.");
+    }
+
+    TypeVariable tType = (TypeVariable) listOfTType.getActualTypeArguments()[0];
+    TypeLiteral<?> t = TypeLiteral.get(tType);
+    try {
+      Key.get(t);
+      fail("Guice should not allow keys for T");
+    } catch (ConfigurationException e) {
+      assertContains(e.getMessage(),
+          "T cannot be used as a key; It is not fully specified.");
+    }
+  }
+
+  public void testCannotGetKeyWithUnspecifiedTypeVariables() {
+    TypeLiteral<Integer> typeLiteral = KeyTest.createTypeLiteral();
+    try {
+      Key.get(typeLiteral);
+      fail("Guice should not allow keys for T");
+    } catch (ConfigurationException e) {
+      assertContains(e.getMessage(),
+          "T cannot be used as a key; It is not fully specified.");
+    }
+  }
+
+  private static <T> TypeLiteral<T> createTypeLiteral() {
+    return new TypeLiteral<T>() {};
+  }
+
+  public void testCannotCreateKeySubclassesWithUnspecifiedTypeVariables() {
+    try {
+      KeyTest.<Integer>createKey();
+      fail("Guice should not allow keys for T");
+    } catch (ConfigurationException e) {
+      assertContains(e.getMessage(),
+          "T cannot be used as a key; It is not fully specified.");
+    }
+  }
+
+  private static <T> Key<T> createKey() {
+    return new Key<T>() {};
+  }
+
+  interface B {}
+
+  @Retention(RUNTIME)
+  @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+  @BindingAnnotation @interface Foo {}
+
+  @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+  @BindingAnnotation @interface Bar {}
+
+  class HasTypeParameters<A, B extends List<A> & Runnable, C extends Runnable> {
+    A a; B b; C c;
+  }
+
+  public void testKeysWithDefaultAnnotations() {
+    AllDefaults allDefaults = HasAnnotations.class.getAnnotation(AllDefaults.class);
+    assertEquals(Key.get(Foo.class, allDefaults), Key.get(Foo.class, AllDefaults.class));
+
+    Marker marker = HasAnnotations.class.getAnnotation(Marker.class);
+    assertEquals(Key.get(Foo.class, marker), Key.get(Foo.class, Marker.class));
+
+    Key<?> noDefaults = Key.get(Foo.class, NoDefaults.class);
+    assertNull(noDefaults.getAnnotation());
+    assertEquals(NoDefaults.class, noDefaults.getAnnotationType());
+
+    Key<?> someDefaults = Key.get(Foo.class, SomeDefaults.class);
+    assertNull(someDefaults.getAnnotation());
+    assertEquals(SomeDefaults.class, someDefaults.getAnnotationType());
+  }
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface AllDefaults {
+    int v1() default 1;
+    String v2() default "foo";
+  }
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface SomeDefaults {
+    int v1() default 1;
+    String v2() default "foo";
+    Class<?> clazz();
+  }
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface NoDefaults {
+    int value();
+  }
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface Marker {
+  }
+
+  @AllDefaults
+  @Marker
+  class HasAnnotations {}
+
+  public void testAnonymousClassesDontHoldRefs() {
+    final AtomicReference<Provider<List<String>>> stringProvider =
+        new AtomicReference<Provider<List<String>>>();
+    final AtomicReference<Provider<List<Integer>>> intProvider =
+        new AtomicReference<Provider<List<Integer>>>();
+    final Object foo = new Object() {
+      @SuppressWarnings("unused") @Inject List<String> list;
+    };
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        bind(new Key<List<String>>() {}).toInstance(new ArrayList<String>());
+        bind(new TypeLiteral<List<Integer>>() {}).toInstance(new ArrayList<Integer>());
+
+        stringProvider.set(getProvider(new Key<List<String>>() {}));
+        intProvider.set(binder().getProvider(Dependency.get(new Key<List<Integer>>() {})));
+
+        binder().requestInjection(new TypeLiteral<Object>() {}, foo);
+      }
+    };
+    WeakReference<Module> moduleRef = new WeakReference<Module>(module);
+    final Injector injector = Guice.createInjector(module);
+    module = null;
+    awaitClear(moduleRef); // Make sure anonymous keys & typeliterals don't hold the module.
+
+    Runnable runner = new Runnable() {
+      @Override public void run() {
+        injector.getInstance(new Key<Typed<String>>() {});
+        injector.getInstance(Key.get(new TypeLiteral<Typed<Integer>>() {}));
+      }
+    };
+    WeakReference<Runnable> runnerRef = new WeakReference<Runnable>(runner);
+    runner.run();
+    runner = null;
+    awaitClear(runnerRef); // also make sure anonymous keys & typeliterals don't hold for JITs
+  }
+
+  static class Typed<T> {}
+
+}
diff --git a/core/test/com/google/inject/LoggerInjectionTest.java b/core/test/com/google/inject/LoggerInjectionTest.java
new file mode 100644
index 0000000..36e5b22
--- /dev/null
+++ b/core/test/com/google/inject/LoggerInjectionTest.java
@@ -0,0 +1,73 @@
+package com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.util.logging.Logger;
+
+/**
+ * Test built-in injection of loggers.
+ *
+ * @author jessewilson
+ */
+public class LoggerInjectionTest extends TestCase {
+
+  @Inject Logger logger;
+
+  public void testLoggerWithMember() {
+    Injector injector = Guice.createInjector();
+    injector.injectMembers(this);
+    assertEquals("com.google.inject.LoggerInjectionTest", logger.getName());
+  }
+  
+  public void testLoggerInConstructor() {
+    Injector injector = Guice.createInjector();
+    Foo foo = injector.getInstance(Foo.class);
+    assertEquals("com.google.inject.LoggerInjectionTest$Foo", foo.logger.getName());
+  }
+  
+  private static class Foo {
+    Logger logger;
+    @SuppressWarnings("unused")
+    @Inject Foo(Logger logger) {
+      this.logger = logger;
+    }
+  }
+  
+  public void testLoggerWithoutMember() {
+    Injector injector = Guice.createInjector();
+    assertNull(injector.getInstance(Logger.class).getName());
+    assertNull(injector.getProvider(Logger.class).get().getName());
+    assertNull(injector.getBinding(Logger.class).getProvider().get().getName());
+    assertEquals("Provider<Logger>", injector.getProvider(Logger.class).toString());
+  }
+
+  public void testCanBindAnnotatedLogger() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Logger.class)
+            .annotatedWith(Names.named("anonymous"))
+            .toInstance(Logger.getAnonymousLogger());
+      }
+    });
+
+    assertNull(injector.getInstance(Key.get(Logger.class, Names.named("anonymous"))).getName());
+  }
+  
+  public void testCannotBindLogger() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(Logger.class).toInstance(Logger.getAnonymousLogger());
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "A binding to java.util.logging.Logger was already configured");
+    }
+  }
+}
diff --git a/core/test/com/google/inject/MembersInjectorTest.java b/core/test/com/google/inject/MembersInjectorTest.java
new file mode 100644
index 0000000..4bb32dd
--- /dev/null
+++ b/core/test/com/google/inject/MembersInjectorTest.java
@@ -0,0 +1,287 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+
+import com.google.inject.name.Names;
+import com.google.inject.util.Providers;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class MembersInjectorTest extends TestCase {
+
+  private static final A<C> uninjectableA = new A<C>() {
+    @Override void doNothing() {
+      throw new AssertionFailedError();
+    }
+  };
+
+  private static final B uninjectableB = new B() {
+    @Override void doNothing() {
+      throw new AssertionFailedError();
+    }
+  };
+
+  private static final C myFavouriteC = new C();
+
+  public void testMembersInjectorFromBinder() {
+    final AtomicReference<MembersInjector<A<C>>> aMembersInjectorReference
+        = new AtomicReference<MembersInjector<A<C>>>();
+    final AtomicReference<MembersInjector<B>> bMembersInjectorReference
+        = new AtomicReference<MembersInjector<B>>();
+
+    Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        MembersInjector<A<C>> aMembersInjector = getMembersInjector(new TypeLiteral<A<C>>() {});
+        try {
+          aMembersInjector.injectMembers(uninjectableA);
+          fail();
+        } catch (IllegalStateException expected) {
+          assertContains(expected.getMessage(),
+              "This MembersInjector cannot be used until the Injector has been created.");
+        }
+
+        MembersInjector<B> bMembersInjector = getMembersInjector(B.class);
+        try {
+          bMembersInjector.injectMembers(uninjectableB);
+          fail();
+        } catch (IllegalStateException expected) {
+          assertContains(expected.getMessage(),
+              "This MembersInjector cannot be used until the Injector has been created.");
+        }
+
+        aMembersInjectorReference.set(aMembersInjector);
+        bMembersInjectorReference.set(bMembersInjector);
+
+        assertEquals("MembersInjector<java.lang.String>",
+            getMembersInjector(String.class).toString());
+
+        bind(C.class).toInstance(myFavouriteC);
+      }
+    });
+
+    A<C> injectableA = new A<C>();
+    aMembersInjectorReference.get().injectMembers(injectableA);
+    assertSame(myFavouriteC, injectableA.t);
+    assertSame(myFavouriteC, injectableA.b.c);
+
+    B injectableB = new B();
+    bMembersInjectorReference.get().injectMembers(injectableB);
+    assertSame(myFavouriteC, injectableB.c);
+
+    B anotherInjectableB = new B();
+    bMembersInjectorReference.get().injectMembers(anotherInjectableB);
+    assertSame(myFavouriteC, anotherInjectableB.c);
+  }
+
+  public void testMembersInjectorFromInjector() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(C.class).toInstance(myFavouriteC);
+      }
+    });
+
+    MembersInjector<A<C>> aMembersInjector
+        = injector.getMembersInjector(new TypeLiteral<A<C>>() {});
+    MembersInjector<B> bMembersInjector = injector.getMembersInjector(B.class);
+
+    A<C> injectableA = new A<C>();
+    aMembersInjector.injectMembers(injectableA);
+    assertSame(myFavouriteC, injectableA.t);
+    assertSame(myFavouriteC, injectableA.b.c);
+
+    B injectableB = new B();
+    bMembersInjector.injectMembers(injectableB);
+    assertSame(myFavouriteC, injectableB.c);
+
+    B anotherInjectableB = new B();
+    bMembersInjector.injectMembers(anotherInjectableB);
+    assertSame(myFavouriteC, anotherInjectableB.c);
+
+    assertEquals("MembersInjector<java.lang.String>",
+        injector.getMembersInjector(String.class).toString());
+  }
+
+  public void testMembersInjectorWithNonInjectedTypes() {
+    Injector injector = Guice.createInjector();
+
+    MembersInjector<NoInjectedMembers> membersInjector
+        = injector.getMembersInjector(NoInjectedMembers.class);
+
+    membersInjector.injectMembers(new NoInjectedMembers());
+    membersInjector.injectMembers(new NoInjectedMembers());
+  }
+
+  public void testInjectionFailure() {
+    Injector injector = Guice.createInjector();
+
+    MembersInjector<InjectionFailure> membersInjector
+        = injector.getMembersInjector(InjectionFailure.class);
+
+    try {
+      membersInjector.injectMembers(new InjectionFailure());
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "1) Error injecting method, java.lang.ClassCastException: whoops, failure #1");
+    }
+  }
+
+  public void testInjectionAppliesToSpecifiedType() {
+    Injector injector = Guice.createInjector();
+
+    MembersInjector<Object> membersInjector = injector.getMembersInjector(Object.class);
+    membersInjector.injectMembers(new InjectionFailure());
+  }
+
+  public void testInjectingMembersInjector() {
+    InjectsMembersInjector injectsMembersInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(C.class).toInstance(myFavouriteC);
+      }
+    }).getInstance(InjectsMembersInjector.class);
+
+    A<C> a = new A<C>();
+    injectsMembersInjector.aMembersInjector.injectMembers(a);
+    assertSame(myFavouriteC, a.t);
+    assertSame(myFavouriteC, a.b.c);
+  }
+
+  public void testCannotBindMembersInjector() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(MembersInjector.class).toProvider(Providers.<MembersInjector>of(null));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Binding to core guice framework type is not allowed: MembersInjector.");
+    }
+
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(new TypeLiteral<MembersInjector<A<C>>>() {})
+              .toProvider(Providers.<MembersInjector<A<C>>>of(null));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Binding to core guice framework type is not allowed: MembersInjector.");
+    }
+  }
+
+  public void testInjectingMembersInjectorWithErrorsInDependencies() {
+    try {
+      Guice.createInjector().getInstance(InjectsBrokenMembersInjector.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for " + Unimplemented.class.getName() + " was bound.",
+          "while locating " + Unimplemented.class.getName(),
+          "for field at " + A.class.getName() + ".t(MembersInjectorTest.java:",
+          "while locating com.google.inject.MembersInjector<",
+          "for field at " + InjectsBrokenMembersInjector.class.getName() + ".aMembersInjector(",
+          "while locating " + InjectsBrokenMembersInjector.class.getName());
+    }
+  }
+
+  public void testLookupMembersInjectorBinding() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(C.class).toInstance(myFavouriteC);
+      }
+    });
+    MembersInjector<A<C>> membersInjector =
+        injector.getInstance(new Key<MembersInjector<A<C>>>() {});
+
+    A<C> a = new A<C>();
+    membersInjector.injectMembers(a);
+    assertSame(myFavouriteC, a.t);
+    assertSame(myFavouriteC, a.b.c);
+
+    assertEquals("MembersInjector<java.lang.String>",
+        injector.getInstance(new Key<MembersInjector<String>>() {}).toString());
+  }
+
+  public void testGettingRawMembersInjector() {
+    Injector injector = Guice.createInjector();
+    try {
+      injector.getInstance(MembersInjector.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "Cannot inject a MembersInjector that has no type parameter");
+    }
+  }
+
+  public void testGettingAnnotatedMembersInjector() {
+    Injector injector = Guice.createInjector();
+    try {
+      injector.getInstance(new Key<MembersInjector<String>>(Names.named("foo")) {});
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for com.google.inject.MembersInjector<java.lang.String> "
+              + "annotated with @com.google.inject.name.Named(value=foo) was bound.");
+    }
+  }
+
+  static class A<T> {
+    @Inject B b;
+    @Inject T t;
+    @Inject void doNothing() {}
+  }
+
+  static class B {
+    @Inject C c;
+    @Inject void doNothing() {}
+  }
+
+  static class C {}
+
+  static class NoInjectedMembers {}
+
+  static class InjectionFailure {
+    int failures = 0;
+
+    @Inject void fail() {
+      throw new ClassCastException("whoops, failure #" + (++failures));
+    }
+  }
+
+  static class InjectsMembersInjector {
+    @Inject MembersInjector<A<C>> aMembersInjector;
+    @Inject A<B> ab;
+  }
+
+  static class InjectsBrokenMembersInjector {
+    @Inject MembersInjector<A<Unimplemented>> aMembersInjector;
+  }
+
+  static interface Unimplemented {}
+}
diff --git a/core/test/com/google/inject/MethodInterceptionTest.java b/core/test/com/google/inject/MethodInterceptionTest.java
new file mode 100644
index 0000000..de39bd9
--- /dev/null
+++ b/core/test/com/google/inject/MethodInterceptionTest.java
@@ -0,0 +1,369 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.inject.matcher.Matchers.only;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.inject.matcher.AbstractMatcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.ConstructorBinding;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class MethodInterceptionTest extends TestCase {
+
+  private AtomicInteger count = new AtomicInteger();
+
+  private final class CountingInterceptor implements MethodInterceptor {
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      count.incrementAndGet();
+      return methodInvocation.proceed();
+    }
+  }
+
+  private final class ReturnNullInterceptor implements MethodInterceptor {
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      return null;
+    }
+  }
+  
+  private final class NoOpInterceptor implements MethodInterceptor {
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      return methodInvocation.proceed();
+    }
+  }
+
+  public void testSharedProxyClasses() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)),
+            new ReturnNullInterceptor());
+      }
+    });
+
+    Injector childOne = injector.createChildInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Interceptable.class);
+      }
+    });
+
+    Interceptable nullFoosOne = childOne.getInstance(Interceptable.class);
+    assertNotNull(nullFoosOne.bar());
+    assertNull(nullFoosOne.foo()); // confirm it's being intercepted
+
+    Injector childTwo = injector.createChildInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Interceptable.class);
+      }
+    });
+
+    Interceptable nullFoosTwo = childTwo.getInstance(Interceptable.class);
+    assertNull(nullFoosTwo.foo()); // confirm it's being intercepted
+
+    assertSame("Child injectors should share proxy classes, otherwise memory leaks!",
+        nullFoosOne.getClass(), nullFoosTwo.getClass());
+    
+    Injector injector2 = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)),
+            new ReturnNullInterceptor());
+      }
+    });
+    Interceptable separateNullFoos = injector2.getInstance(Interceptable.class);
+    assertNull(separateNullFoos.foo()); // confirm it's being intercepted
+    assertSame("different injectors should share proxy classes, otherwise memory leaks!",
+        nullFoosOne.getClass(), separateNullFoos.getClass());
+  }
+
+  public void testGetThis() {
+    final AtomicReference<Object> lastTarget = new AtomicReference<Object>();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.any(), new MethodInterceptor() {
+          public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+            lastTarget.set(methodInvocation.getThis());
+            return methodInvocation.proceed();
+          }
+        });
+      }
+    });
+
+    Interceptable interceptable = injector.getInstance(Interceptable.class);
+    interceptable.foo();
+    assertSame(interceptable, lastTarget.get());
+  }
+
+  public void testInterceptingFinalClass() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.any(), new MethodInterceptor() {
+          public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+            return methodInvocation.proceed();
+          }
+        });
+      }
+    });
+    try {
+      injector.getInstance(NotInterceptable.class);
+      fail();
+    } catch(ConfigurationException ce) {
+      assertEquals("Unable to method intercept: " + NotInterceptable.class.getName(),
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage().toString());
+      assertEquals("Cannot subclass final class class " + NotInterceptable.class.getName(),
+          ce.getCause().getMessage());
+    }
+  }
+
+  public void testSpiAccessToInterceptors() throws NoSuchMethodException {
+    final MethodInterceptor countingInterceptor = new CountingInterceptor();
+    final MethodInterceptor returnNullInterceptor = new ReturnNullInterceptor();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(),Matchers.returns(only(Foo.class)),
+            countingInterceptor);
+        bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class).or(only(Bar.class))),
+            returnNullInterceptor);
+      }
+    });
+
+    ConstructorBinding<?> interceptedBinding
+        = (ConstructorBinding<?>) injector.getBinding(Interceptable.class);
+    Method barMethod = Interceptable.class.getMethod("bar");
+    Method fooMethod = Interceptable.class.getMethod("foo");
+    assertEquals(ImmutableMap.<Method, List<MethodInterceptor>>of(
+        fooMethod, ImmutableList.of(countingInterceptor, returnNullInterceptor),
+        barMethod, ImmutableList.of(returnNullInterceptor)),
+        interceptedBinding.getMethodInterceptors());
+
+    ConstructorBinding<?> nonInterceptedBinding
+        = (ConstructorBinding<?>) injector.getBinding(Foo.class);
+    assertEquals(ImmutableMap.<Method, List<MethodInterceptor>>of(),
+        nonInterceptedBinding.getMethodInterceptors());
+
+    injector.getInstance(Interceptable.class).foo();
+    assertEquals("expected counting interceptor to be invoked first", 1, count.get());
+  }
+
+  public void testInterceptedMethodThrows() throws Exception {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.any(), new CountingInterceptor());
+        bindInterceptor(Matchers.any(), Matchers.any(), new CountingInterceptor());
+      }
+    });
+
+    Interceptable interceptable = injector.getInstance(Interceptable.class);
+    try {
+      interceptable.explode();
+      fail();
+    } catch (Exception e) {
+      // validate all causes.
+      for (Throwable t = e; t != null; t = t.getCause()) {
+        StackTraceElement[] stackTraceElement = t.getStackTrace();
+        assertEquals("explode", stackTraceElement[0].getMethodName());
+        assertEquals("invoke", stackTraceElement[1].getMethodName());
+        assertEquals("invoke", stackTraceElement[2].getMethodName());
+        assertEquals("testInterceptedMethodThrows", stackTraceElement[3].getMethodName());
+      }
+    }
+  }
+  
+  public void testNotInterceptedMethodsInInterceptedClassDontAddFrames() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)),
+            new NoOpInterceptor());
+      }
+    });
+
+    Interceptable interceptable = injector.getInstance(Interceptable.class);
+    assertNull(interceptable.lastElements);
+    interceptable.foo();
+    boolean cglibFound = false;
+    for (int i = 0; i < interceptable.lastElements.length; i++) {
+      if (interceptable.lastElements[i].toString().contains("cglib")) {
+        cglibFound = true;
+        break;
+      }
+    }
+    assertTrue(Arrays.toString(interceptable.lastElements), cglibFound);
+    cglibFound = false;
+    
+    interceptable.bar();
+    for (int i = 0; i < interceptable.lastElements.length; i++) {
+      if (interceptable.lastElements[i].toString().contains("cglib")) {
+        cglibFound = true;
+        break;
+      }
+    }
+    assertFalse(Arrays.toString(interceptable.lastElements), cglibFound);
+  }
+
+  static class Foo {}
+  static class Bar {}
+
+  public static class Interceptable {
+    StackTraceElement[] lastElements; 
+    
+    public Foo foo() {
+      lastElements = Thread.currentThread().getStackTrace();
+      return new Foo() {};
+    }
+    public Bar bar() {
+      lastElements = Thread.currentThread().getStackTrace();
+      return new Bar() {};
+    }
+    public String explode() throws Exception {
+      lastElements = Thread.currentThread().getStackTrace();
+      throw new Exception("kaboom!", new RuntimeException("boom!"));
+    }
+  }
+
+  public static final class NotInterceptable {}
+  
+  public void testInterceptingNonBridgeWorks() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Interface.class).to(Impl.class);
+        bindInterceptor(Matchers.any(), new AbstractMatcher<Method>() {
+          public boolean matches(Method t) {
+            return !t.isBridge() && t.getDeclaringClass() != Object.class;
+          }
+        }, new CountingInterceptor());
+      }
+    });
+    Interface intf = injector.getInstance(Interface.class);
+    assertEquals(0, count.get());
+    intf.aMethod(null);
+    assertEquals(1, count.get());
+  }
+  
+  static class ErasedType {}
+  static class RetType extends ErasedType {}  
+  static abstract class Superclass<T extends ErasedType> {
+      public T aMethod(T t) { return null; }
+  }
+  public interface Interface {
+      RetType aMethod(RetType obj);
+  }
+  public static class Impl extends Superclass<RetType> implements Interface {
+  }
+  
+  public void testInterceptionOrder() {
+    final List<String> callList = Lists.newArrayList();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.any(), 
+          new NamedInterceptor("a", callList),
+          new NamedInterceptor("b", callList),
+          new NamedInterceptor("c", callList));
+      }
+    });
+
+    Interceptable interceptable = injector.getInstance(Interceptable.class);
+    assertEquals(0, callList.size());
+    interceptable.foo();
+    assertEquals(Arrays.asList("a", "b", "c"), callList);
+  }
+  
+  private final class NamedInterceptor implements MethodInterceptor {
+    private final String name;
+    final List<String> called;
+    
+    NamedInterceptor(String name, List<String> callList) {
+      this.name = name;
+      this.called = callList;
+    }
+    
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      called.add(name);
+      return methodInvocation.proceed();
+    }
+  }
+  
+  public void testDeDuplicateInterceptors() throws Exception {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        CountingInterceptor interceptor = new CountingInterceptor();
+        bindInterceptor(Matchers.any(), Matchers.any(), interceptor);
+        bindInterceptor(Matchers.any(), Matchers.any(), interceptor);
+      }
+    });
+
+    Interceptable interceptable = injector.getInstance(Interceptable.class);
+    interceptable.foo();
+    assertEquals(1, count.get());
+  }
+
+  public void testCallLater() {
+    final Queue<Runnable> queue = Lists.newLinkedList();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.any(), new CallLaterInterceptor(queue));
+      }
+    });
+
+    Interceptable interceptable = injector.getInstance(Interceptable.class);
+    interceptable.foo();
+    assertNull(interceptable.lastElements);
+    assertEquals(1, queue.size());
+
+    queue.remove().run();
+    assertNotNull(interceptable.lastElements);
+  }
+
+  private final class CallLaterInterceptor implements MethodInterceptor {
+    private final Queue<Runnable> queue;
+
+    public CallLaterInterceptor(Queue<Runnable> queue) {
+      this.queue = queue;
+    }
+
+    public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
+      queue.add(new Runnable() {
+        @Override
+        public void run() {
+          try {
+            methodInvocation.proceed();
+          } catch (Throwable t) {
+            throw new RuntimeException(t);
+          }
+        }
+      });
+      return null;
+    }
+  }
+}
diff --git a/core/test/com/google/inject/ModuleTest.java b/core/test/com/google/inject/ModuleTest.java
new file mode 100644
index 0000000..e938da5
--- /dev/null
+++ b/core/test/com/google/inject/ModuleTest.java
@@ -0,0 +1,56 @@
+// Copyright 2007 Google Inc. All Rights Reserved.
+
+package com.google.inject;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests relating to modules.
+ *
+ * @author kevinb
+ */
+public class ModuleTest extends TestCase {
+
+  static class A implements Module {
+    public void configure(Binder binder) {
+      binder.bind(X.class);
+      binder.install(new B());
+      binder.install(new C());
+    }
+  }
+
+  static class B implements Module {
+    public void configure(Binder binder) {
+      binder.bind(Y.class);
+      binder.install(new D());
+    }
+  }
+
+  static class C implements Module {
+    public void configure(Binder binder) {
+      binder.bind(Z.class);
+      binder.install(new D());
+    }
+  }
+
+  static class D implements Module {
+    public void configure(Binder binder) {
+      binder.bind(W.class);
+    }
+    @Override public boolean equals(Object obj) {
+      return obj.getClass() == D.class; // we're all equal in the eyes of guice
+    }
+    @Override public int hashCode() {
+      return D.class.hashCode();
+    }
+  }
+
+  static class X {}
+  static class Y {}
+  static class Z {}
+  static class W {}
+
+  public void testDiamond() throws Exception {
+    Guice.createInjector(new A());
+  }
+}
diff --git a/core/test/com/google/inject/ModulesTest.java b/core/test/com/google/inject/ModulesTest.java
new file mode 100644
index 0000000..b32e4f6
--- /dev/null
+++ b/core/test/com/google/inject/ModulesTest.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (C) 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.inject;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.spi.ElementSource;
+import com.google.inject.util.Modules;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class ModulesTest extends TestCase {
+
+  public void testCombineVarargs() {
+    Module combined = Modules.combine(newModule(1), newModule(2L), newModule((short) 3));
+    Injector injector = Guice.createInjector(combined);
+    assertEquals(1, injector.getInstance(Integer.class).intValue());
+    assertEquals(2L, injector.getInstance(Long.class).longValue());
+    assertEquals(3, injector.getInstance(Short.class).shortValue());
+  }
+  
+  public void testCombineIterable() {
+    Iterable<Module> modules = Arrays.asList(newModule(1), newModule(2L), newModule((short) 3));
+    Injector injector = Guice.createInjector(Modules.combine(modules));
+    assertEquals(1, injector.getInstance(Integer.class).intValue());
+    assertEquals(2, injector.getInstance(Long.class).longValue());
+    assertEquals(3, injector.getInstance(Short.class).shortValue());
+  }
+
+  /**
+   * The module returned by Modules.combine shouldn't show up in binder sources.
+   */
+  public void testCombineSources() {
+    final Module m1 = newModule(1);
+    final Module m2 = newModule(2L);
+    final Module combined1 = Modules.combine(m1, m2);
+    Module skipSourcesModule = new AbstractModule() {
+      @Override protected void configure() {
+        install(combined1);
+      }
+    };
+    final Module combined2 = Modules.combine(skipSourcesModule);
+    Injector injector = Guice.createInjector(combined2);
+    ElementSource source = (ElementSource) injector.getBinding(Integer.class).getSource();
+    assertEquals(source.getModuleClassNames().size(), 4);
+    assertEquals(ImmutableList.of(m1.getClass().getName(),
+        combined1.getClass().getName(), skipSourcesModule.getClass().getName(),
+        combined2.getClass().getName()), source.getModuleClassNames());
+    StackTraceElement stackTraceElement = (StackTraceElement) source.getDeclaringSource();
+    assertEquals(skipSourcesModule.getClass().getName(), stackTraceElement.getClassName());
+  }
+
+  private <T> Module newModule(final T toBind) {
+    return new AbstractModule() {
+      protected void configure() {
+        @SuppressWarnings("unchecked") // getClass always needs a cast
+        Class<T> tClass = (Class<T>) toBind.getClass();
+        binder().skipSources(getClass()).bind(tClass).toInstance(toBind);
+      }
+    };
+  }
+}
diff --git a/core/test/com/google/inject/NullableInjectionPointTest.java b/core/test/com/google/inject/NullableInjectionPointTest.java
new file mode 100644
index 0000000..9cf22cc
--- /dev/null
+++ b/core/test/com/google/inject/NullableInjectionPointTest.java
@@ -0,0 +1,251 @@
+package com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class NullableInjectionPointTest extends TestCase {
+
+  public void testInjectNullIntoNotNullableConstructor() {
+    try {
+      createInjector().getInstance(FooConstructor.class);
+      fail("Injecting null should fail with an error");
+    }
+    catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "null returned by binding at " + getClass().getName(),
+          "parameter 0 of " + FooConstructor.class.getName() + ".<init>() is not @Nullable");
+    }
+  }
+
+  public void testInjectNullIntoNotNullableMethod() {
+    try {
+      createInjector().getInstance(FooMethod.class);
+      fail("Injecting null should fail with an error");
+    }
+    catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "null returned by binding at " + getClass().getName(),
+          "parameter 0 of " + FooMethod.class.getName() + ".setFoo() is not @Nullable");
+    }
+  }
+
+  public void testInjectNullIntoNotNullableField() {
+    try {
+      createInjector().getInstance(FooField.class);
+      fail("Injecting null should fail with an error");
+    }
+    catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "null returned by binding at " + getClass().getName(),
+          " but " + FooField.class.getName() + ".foo is not @Nullable");
+    }
+  }
+
+  /**
+   * Provider.getInstance() is allowed to return null via direct calls to
+   * getInstance().
+   */
+  public void testGetInstanceOfNull() {
+    assertNull(createInjector().getInstance(Foo.class));
+  }
+
+  public void testInjectNullIntoNullableConstructor() {
+    NullableFooConstructor nfc
+        = createInjector().getInstance(NullableFooConstructor.class);
+    assertNull(nfc.foo);
+  }
+
+  public void testInjectNullIntoNullableMethod() {
+    NullableFooMethod nfm
+        = createInjector().getInstance(NullableFooMethod.class);
+    assertNull(nfm.foo);
+  }
+
+  public void testInjectNullIntoNullableField() {
+    NullableFooField nff
+        = createInjector().getInstance(NullableFooField.class);
+    assertNull(nff.foo);
+  }
+  
+  public void testInjectNullIntoCustomNullableConstructor() {
+    CustomNullableFooConstructor nfc
+        = createInjector().getInstance(CustomNullableFooConstructor.class);
+    assertNull(nfc.foo);
+  }
+
+  public void testInjectNullIntoCustomNullableMethod() {
+    CustomNullableFooMethod nfm
+        = createInjector().getInstance(CustomNullableFooMethod.class);
+    assertNull(nfm.foo);
+  }
+
+  public void testInjectNullIntoCustomNullableField() {
+    CustomNullableFooField nff
+        = createInjector().getInstance(CustomNullableFooField.class);
+    assertNull(nff.foo);
+  }  
+
+  private Injector createInjector() {
+    return Guice.createInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bind(Foo.class).toProvider(new Provider<Foo>() {
+              public Foo get() {
+                return null;
+              }
+            });
+          }
+        });
+  }
+
+  /**
+   * We haven't decided on what the desired behaviour of this test should be...
+   */
+  public void testBindNullToInstance() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(Foo.class).toInstance(null);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Binding to null instances is not allowed.",
+          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  public void testBindNullToProvider() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class).toProvider(new Provider<Foo>() {
+          public Foo get() {
+            return null;
+          }
+        });
+      }
+    });
+    assertNull(injector.getInstance(NullableFooField.class).foo);
+    assertNull(injector.getInstance(CustomNullableFooField.class).foo);
+
+    try {
+      injector.getInstance(FooField.class);
+    }
+    catch(ProvisionException expected) {
+      assertContains(expected.getMessage(), "null returned by binding at");
+    }
+  }
+
+  public void testBindScopedNull() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class).toProvider(new Provider<Foo>() {
+          public Foo get() {
+            return null;
+          }
+        }).in(Scopes.SINGLETON);
+      }
+    });
+    assertNull(injector.getInstance(NullableFooField.class).foo);
+    assertNull(injector.getInstance(CustomNullableFooField.class).foo);
+
+    try {
+      injector.getInstance(FooField.class);
+    }
+    catch(ProvisionException expected) {
+      assertContains(expected.getMessage(), "null returned by binding at");
+    }
+  }
+
+  public void testBindNullAsEagerSingleton() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class).toProvider(new Provider<Foo>() {
+          public Foo get() {
+            return null;
+          }
+        }).asEagerSingleton();
+      }
+    });
+    assertNull(injector.getInstance(NullableFooField.class).foo);
+    assertNull(injector.getInstance(CustomNullableFooField.class).foo);
+
+    try {
+      injector.getInstance(FooField.class);
+      fail();
+    } catch(ProvisionException expected) {
+      assertContains(expected.getMessage(), "null returned by binding "
+          + "at com.google.inject.NullableInjectionPointTest");
+    }
+  }
+
+  static class Foo { }
+
+  static class FooConstructor {
+    @Inject FooConstructor(Foo foo) { }
+  }
+  static class FooField {
+    @Inject Foo foo;
+  }
+  static class FooMethod {
+    @Inject
+    void setFoo(Foo foo) { }
+  }
+
+  static class NullableFooConstructor {
+    Foo foo;
+    @Inject NullableFooConstructor(@Nullable Foo foo) {
+      this.foo = foo;
+    }
+  }
+  static class NullableFooField {
+    @Inject @Nullable Foo foo;
+  }
+  static class NullableFooMethod {
+    Foo foo;
+    @Inject void setFoo(@Nullable Foo foo) {
+      this.foo = foo;
+    }
+  }
+  
+  static class CustomNullableFooConstructor {
+    Foo foo;
+    @Inject CustomNullableFooConstructor(@Namespace.Nullable Foo foo) {
+      this.foo = foo;
+    }
+  }
+  
+  static class CustomNullableFooField {
+    @Inject @Namespace.Nullable Foo foo;
+  }
+  static class CustomNullableFooMethod {
+    Foo foo;
+    @Inject void setFoo(@Namespace.Nullable Foo foo) {
+      this.foo = foo;
+    }
+  }
+
+  @Documented
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target({ElementType.PARAMETER, ElementType.FIELD})
+  @interface Nullable { }
+  
+  static interface Namespace {
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER, ElementType.FIELD})
+    @interface Nullable { }
+  }
+}
diff --git a/core/test/com/google/inject/OptionalBindingTest.java b/core/test/com/google/inject/OptionalBindingTest.java
new file mode 100644
index 0000000..a62191c
--- /dev/null
+++ b/core/test/com/google/inject/OptionalBindingTest.java
@@ -0,0 +1,298 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.inject.Asserts.assertContains;
+
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+/**
+ * This test verifies the ways things are injected (ie. getInstance(),
+ * injectMembers(), bind to instance, and bind to provider instance) for all
+ * states of optional bindings (fields, methods, multiple-argument methods,
+ * provider fields, provider methods, constructors).
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class OptionalBindingTest extends TestCase {
+
+  private static final A injectA = new A() {};
+  private static final B injectB = new B() {};
+  private static final C injectC = new C() {};
+  private static final D injectD = new D() {};
+  private static final E injectE = new E() {};
+  private static final F injectF = new F() {};
+  private static final G injectG = new G() {};
+
+  private Module everythingModule = new AbstractModule() {
+    protected void configure() {
+      bind(A.class).toInstance(injectA);
+      bind(B.class).toInstance(injectB);
+      bind(C.class).toInstance(injectC);
+      bind(D.class).toInstance(injectD);
+      bind(E.class).annotatedWith(Names.named("e")).toInstance(injectE);
+      bind(F.class).toInstance(injectF);
+      bind(G.class).toInstance(injectG);
+    }
+  };
+
+  private Module partialModule = new AbstractModule() {
+    protected void configure() {
+      bind(C.class).toInstance(new C() {});
+    }
+  };
+
+  private Module toInstanceModule = new AbstractModule() {
+    protected void configure() {
+      bind(HasOptionalInjections.class)
+          .toInstance(new HasOptionalInjections());
+    }
+  };
+
+  private Module toProviderInstanceModule = new AbstractModule() {
+    protected void configure() {
+      bind(HasOptionalInjections.class)
+          .toProvider(new HasOptionalInjectionsProvider());
+    }
+  };
+
+  private Module toProviderModule = new AbstractModule() {
+    protected void configure() {
+      bind(HasOptionalInjections.class)
+          .toProvider(HasOptionalInjectionsProvider.class);
+    }
+  };
+
+  public void testEverythingInjectorGetInstance() {
+    Guice.createInjector(everythingModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertEverythingInjected();
+  }
+
+  public void testPartialInjectorGetInstance() {
+    Guice.createInjector(partialModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertNothingInjected();
+  }
+
+  public void testNothingInjectorGetInstance() {
+    Guice.createInjector()
+        .getInstance(HasOptionalInjections.class)
+        .assertNothingInjected();
+  }
+
+  public void testEverythingInjectorInjectMembers() {
+    HasOptionalInjections instance = new HasOptionalInjections();
+    Guice.createInjector(everythingModule).injectMembers(instance);
+    instance.assertEverythingInjected();
+  }
+
+  public void testPartialInjectorInjectMembers() {
+    HasOptionalInjections instance = new HasOptionalInjections();
+    Guice.createInjector(partialModule).injectMembers(instance);
+    instance.assertNothingInjected();
+  }
+
+  public void testNothingInjectorInjectMembers() {
+    HasOptionalInjections instance = new HasOptionalInjections();
+    Guice.createInjector().injectMembers(instance);
+    instance.assertNothingInjected();
+  }
+
+  public void testEverythingInjectorToInstance() {
+    Guice.createInjector(everythingModule, toInstanceModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertEverythingInjected();
+  }
+
+  public void testPartialInjectorToInstance() {
+    Guice.createInjector(partialModule, toInstanceModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertNothingInjected();
+  }
+
+  public void testNothingInjectorToInstance() {
+    Guice.createInjector(toInstanceModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertNothingInjected();
+  }
+  
+  public void testEverythingInjectorToProviderInstance() {
+    Guice.createInjector(everythingModule, toProviderInstanceModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertEverythingInjected();
+  }
+
+  public void testPartialInjectorToProviderInstance() {
+    Guice.createInjector(partialModule, toProviderInstanceModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertNothingInjected();
+  }
+
+  public void testNothingInjectorToProviderInstance() {
+    Guice.createInjector(toProviderInstanceModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertNothingInjected();
+  }
+
+  public void testEverythingInjectorToProvider() {
+    Guice.createInjector(everythingModule, toProviderModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertEverythingInjected();
+  }
+
+  public void testPartialInjectorToProvider() {
+    Guice.createInjector(partialModule, toProviderModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertNothingInjected();
+  }
+
+  public void testNothingInjectorToProvider() {
+    Guice.createInjector(toProviderModule)
+        .getInstance(HasOptionalInjections.class)
+        .assertNothingInjected();
+  }
+
+  static class HasOptionalInjections {
+    A originalA = new A() {};
+    @Inject(optional=true) A a = originalA; // field injection
+    B b; // method injection with one argument
+    C c; // method injection with two arguments
+    D d; // method injection with two arguments
+    E e; // annotated injection
+    @Inject(optional=true) Provider<F> fProvider; // provider
+    Provider<G> gProvider; // method injection of provider
+    boolean invoked0, invoked1, invoked2, invokedAnnotated, invokeProvider;
+
+    @Inject(optional=true) void methodInjectZeroArguments() {
+      invoked0 = true;
+    }
+
+    @Inject(optional=true) void methodInjectOneArgument(B b) {
+      this.b = b;
+      invoked1 = true;
+    }
+
+    @Inject(optional=true) void methodInjectTwoArguments(C c, D d) {
+      this.c = c;
+      this.d = d;
+      invoked2 = true;
+    }
+
+    @Inject(optional=true) void methodInjectAnnotated(@Named("e") E e) {
+      this.e = e;
+      invokedAnnotated = true;
+    }
+
+    @Inject(optional=true) void methodInjectProvider(Provider<G> gProvider) {
+      this.gProvider = gProvider;
+      invokeProvider = true;
+    }
+
+    void assertNothingInjected() {
+      assertSame(originalA, a);
+      assertNull(b);
+      assertNull(c);
+      assertNull(d);
+      assertNull(e);
+      assertNull(fProvider);
+      assertNull(gProvider);
+      assertTrue(invoked0);
+      assertFalse(invoked1);
+      assertFalse(invoked2);
+      assertFalse(invokedAnnotated);
+    }
+
+    public void assertEverythingInjected() {
+      assertNotSame(injectA, originalA);
+      assertSame(injectA, a);
+      assertSame(injectB, b);
+      assertSame(injectC, c);
+      assertSame(injectD, d);
+      assertSame(injectE, e);
+      assertSame(injectF, fProvider.get());
+      assertSame(injectG, gProvider.get());
+      assertTrue(invoked0);
+      assertTrue(invoked1);
+      assertTrue(invoked2);
+      assertTrue(invokedAnnotated);
+    }
+  }
+
+  static class HasOptionalInjectionsProvider
+      extends HasOptionalInjections implements Provider<HasOptionalInjections> {
+    public HasOptionalInjections get() {
+      return this;
+    }
+  }
+
+  public void testOptionalConstructorBlowsUp() {
+    try {
+      Guice.createInjector().getInstance(HasOptionalConstructor.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), "OptionalBindingTest$HasOptionalConstructor.<init>() "
+          + "is annotated @Inject(optional=true), but constructors cannot be optional.");
+    }
+  }
+
+  static class HasOptionalConstructor {
+    // Suppress compiler errors by the error-prone checker InjectedConstructorAnnotations,
+    // which catches optional injected constructors.
+    @SuppressWarnings("InjectedConstructorAnnotations")
+    @Inject(optional=true)
+    HasOptionalConstructor() {}
+  }
+
+  @Inject(optional=true) static A staticInjectA;
+
+  public void testStaticInjection() {
+    staticInjectA = injectA;
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        requestStaticInjection(OptionalBindingTest.class);
+      }
+    });
+    assertSame(staticInjectA, injectA);
+  }
+
+  /**
+   * Test for bug 107, where we weren't doing optional injection properly for
+   * indirect injections.
+   */
+  public void testIndirectOptionalInjection() {
+    Indirect indirect = Guice.createInjector().getInstance(Indirect.class);
+    assertNotNull(indirect.hasOptionalInjections);
+    indirect.hasOptionalInjections.assertNothingInjected();
+  }
+
+  static class Indirect {
+    @Inject HasOptionalInjections hasOptionalInjections;
+  }
+
+  interface A {}
+  interface B {}
+  interface C {}
+  interface D {}
+  interface E {}
+  interface F {}
+  interface G {}
+}
diff --git a/core/test/com/google/inject/ParentInjectorTest.java b/core/test/com/google/inject/ParentInjectorTest.java
new file mode 100644
index 0000000..4940b77
--- /dev/null
+++ b/core/test/com/google/inject/ParentInjectorTest.java
@@ -0,0 +1,331 @@
+/*
+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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.name.Names;
+import com.google.inject.spi.TypeConverter;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.List;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class ParentInjectorTest extends TestCase {
+
+  public void testParentAndChildCannotShareExplicitBindings() {
+    Injector parent = Guice.createInjector(bindsA);
+    try {
+      parent.createChildInjector(bindsA);
+      fail("Created the same explicit binding on both parent and child");
+    } catch (CreationException e) {
+      assertContains(e.getMessage(), "A binding to ", A.class.getName(), " was already configured",
+          " at ", getClass().getName(), getDeclaringSourcePart(getClass()),
+          " at ", getClass().getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  public void testParentJitBindingWontClobberChildBinding() {
+    Injector parent = Guice.createInjector();
+    parent.createChildInjector(bindsA);
+    try {
+      parent.getInstance(A.class);
+      fail("Created a just-in-time binding on the parent that's the same as a child's binding");
+    } catch (ConfigurationException e) {
+      assertContains(e.getMessage(),
+          "Unable to create binding for " + A.class.getName(),
+          "It was already configured on one or more child injectors or private modules",
+          "bound at " + bindsA.getClass().getName() + ".configure(",
+          "If it was in a PrivateModule, did you forget to expose the binding?",
+          "while locating " + A.class.getName());
+    }
+  }
+  
+  public void testChildCannotBindToAParentJitBinding() {
+    Injector parent = Guice.createInjector();
+    parent.getInstance(A.class);
+    try {
+      parent.createChildInjector(bindsA);
+      fail();
+    } catch(CreationException ce) {
+      assertContains(Iterables.getOnlyElement(ce.getErrorMessages()).getMessage(),
+          "A just-in-time binding to " + A.class.getName() + " was already configured on a parent injector.");
+    }    
+  }
+
+  public void testJustInTimeBindingsAreSharedWithParentIfPossible() {
+    Injector parent = Guice.createInjector();
+    Injector child = parent.createChildInjector();
+    assertSame(child.getInstance(A.class), parent.getInstance(A.class));
+
+    Injector anotherChild = parent.createChildInjector();
+    assertSame(anotherChild.getInstance(A.class), parent.getInstance(A.class));
+
+    Injector grandchild = child.createChildInjector();
+    assertSame(grandchild.getInstance(A.class), parent.getInstance(A.class));
+  }
+
+  public void testBindingsInherited() {
+    Injector parent = Guice.createInjector(bindsB);
+    Injector child = parent.createChildInjector();
+    assertSame(RealB.class, child.getInstance(B.class).getClass());
+  }
+
+  public void testGetParent() {
+    Injector top = Guice.createInjector(bindsA);
+    Injector middle = top.createChildInjector(bindsB);
+    Injector bottom = middle.createChildInjector();
+    assertSame(middle, bottom.getParent());
+    assertSame(top, middle.getParent());
+    assertNull(top.getParent());
+  }
+
+  public void testChildBindingsNotVisibleToParent() {
+    Injector parent = Guice.createInjector();
+    parent.createChildInjector(bindsB);
+    try {
+      parent.getBinding(B.class);
+      fail();
+    } catch (ConfigurationException expected) {
+    }
+  }
+
+  public void testScopesInherited() {
+    Injector parent = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(MyScope.class, Scopes.SINGLETON);
+      }
+    });
+    Injector child = parent.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(A.class).in(MyScope.class);
+      }
+    });
+    assertSame(child.getInstance(A.class), child.getInstance(A.class));
+  }
+
+  /*if[AOP]*/
+  private final org.aopalliance.intercept.MethodInterceptor returnNullInterceptor
+      = new org.aopalliance.intercept.MethodInterceptor() {
+    public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) {
+      return null;
+    }
+  };
+
+  public void testInterceptorsInherited() {
+    Injector parent = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        super.bindInterceptor(Matchers.any(), Matchers.returns(Matchers.identicalTo(A.class)),
+            returnNullInterceptor);
+      }
+    });
+
+    Injector child = parent.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(C.class);
+      }
+    });
+
+    assertNull(child.getInstance(C.class).interceptedMethod());
+  }
+  /*end[AOP]*/
+
+  public void testTypeConvertersInherited() {
+    Injector parent = Guice.createInjector(bindListConverterModule);
+    Injector child = parent.createChildInjector(bindStringNamedB);
+
+    assertEquals(ImmutableList.of(), child.getInstance(Key.get(List.class, Names.named("B"))));
+  }
+
+  public void testTypeConvertersConflicting() {
+    Injector parent = Guice.createInjector(bindListConverterModule);
+    Injector child = parent.createChildInjector(bindListConverterModule, bindStringNamedB);
+
+    try {
+      child.getInstance(Key.get(List.class, Names.named("B")));
+      fail();
+    } catch (ConfigurationException expected) {
+      Asserts.assertContains(expected.getMessage(), "Multiple converters can convert");
+    }
+  }
+
+  public void testInjectorInjectionSpanningInjectors() {
+    Injector parent = Guice.createInjector();
+    Injector child = parent.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(D.class);
+      }
+    });
+
+    D d = child.getInstance(D.class);
+    assertSame(d.injector, child);
+
+    E e = child.getInstance(E.class);
+    assertSame(e.injector, parent);
+  }
+
+  public void testSeveralLayersOfHierarchy() {
+    Injector top = Guice.createInjector(bindsA);
+    Injector left = top.createChildInjector();
+    Injector leftLeft = left.createChildInjector(bindsD);
+    Injector right = top.createChildInjector(bindsD);
+    
+    assertSame(leftLeft, leftLeft.getInstance(D.class).injector);
+    assertSame(right, right.getInstance(D.class).injector);
+    assertSame(top, leftLeft.getInstance(E.class).injector);
+    assertSame(top.getInstance(A.class), leftLeft.getInstance(A.class));
+
+    Injector leftRight = left.createChildInjector(bindsD);
+    assertSame(leftRight, leftRight.getInstance(D.class).injector);
+
+    try {
+      top.getInstance(D.class);
+      fail();
+    } catch (ConfigurationException expected) {
+    }
+
+    try {
+      left.getInstance(D.class);
+      fail();
+    } catch (ConfigurationException expected) {
+    }
+  }
+
+  public void testScopeBoundInChildInjectorOnly() {
+    Injector parent = Guice.createInjector();
+    Injector child = parent.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(MyScope.class, Scopes.SINGLETON);
+      }
+    });
+
+    try {
+      parent.getProvider(F.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "No scope is bound to com.google.inject.ParentInjectorTest$MyScope.",
+          "at " + F.class.getName() + ".class(ParentInjectorTest.java",
+          "  while locating " + F.class.getName());
+    }
+    
+    assertNotNull(child.getProvider(F.class).get());
+  }
+
+  public void testErrorInParentButOkayInChild() {
+    Injector parent = Guice.createInjector();
+    Injector childInjector = parent.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(MyScope.class, Scopes.SINGLETON);
+        bind(Object.class).to(F.class);
+      }
+    });
+    Object one = childInjector.getInstance(Object.class);
+    Object two = childInjector.getInstance(Object.class);
+    assertSame(one, two);
+  }
+
+  public void testErrorInParentAndChild() {
+    Injector parent = Guice.createInjector();
+    Injector childInjector = parent.createChildInjector();
+
+    try {
+      childInjector.getInstance(G.class);
+      fail();
+    } catch(ConfigurationException expected) {
+      assertContains(expected.getMessage(), "No scope is bound to " + MyScope.class.getName(),
+          "at " + F.class.getName() + ".class(ParentInjectorTest.java:",
+          "  while locating " + G.class.getName());
+    }
+  }
+
+  @Singleton
+  static class A {}
+
+  private final Module bindsA = new AbstractModule() {
+    @Override protected void configure() {
+      bind(A.class).toInstance(new A());
+    }
+  };
+
+  interface B {}
+  static class RealB implements B {}
+
+  private final Module bindsB = new AbstractModule() {
+    @Override protected void configure() {
+      bind(B.class).to(RealB.class);
+    }
+  };
+
+  @Target(TYPE) @Retention(RUNTIME) @ScopeAnnotation
+  public @interface MyScope {}
+
+  private final TypeConverter listConverter = new TypeConverter() {
+    public Object convert(String value, TypeLiteral<?> toType) {
+      return ImmutableList.of();
+    }
+  };
+
+  private final Module bindListConverterModule = new AbstractModule() {
+    @Override protected void configure() {
+      convertToTypes(Matchers.any(), listConverter);
+    }
+  };
+
+  private final Module bindStringNamedB = new AbstractModule() {
+    @Override protected void configure() {
+      bind(String.class).annotatedWith(Names.named("B")).toInstance("buzz");
+    }
+  };
+
+  public static class C {
+    public A interceptedMethod() {
+      return new A();
+    }
+  }
+
+  static class D {
+    @Inject Injector injector;
+  }
+
+  static class E {
+    @Inject Injector injector;
+  }
+
+  private final Module bindsD = new AbstractModule() {
+    @Override protected void configure() {
+      bind(D.class);
+    }
+  };
+
+  @MyScope
+  static class F implements G {}
+
+  @ImplementedBy(F.class)
+  interface G {}
+}
diff --git a/core/test/com/google/inject/PerformanceComparison.java b/core/test/com/google/inject/PerformanceComparison.java
new file mode 100644
index 0000000..a6351a3
--- /dev/null
+++ b/core/test/com/google/inject/PerformanceComparison.java
@@ -0,0 +1,298 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertSame;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.config.ConstructorArgumentValues;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+
+import java.lang.annotation.Retention;
+import java.text.DecimalFormat;
+import java.util.concurrent.Callable;
+
+/**
+ * A semi-useless microbenchmark. Spring and Guice constuct the same object
+ * graph a bunch of times, and we see who can construct the most per second.
+ * As of this writing Guice is more than 50X faster. Also useful for comparing 
+ * pure Java configuration options.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class PerformanceComparison {
+
+  public static void main(String[] args) throws Exception {
+    // Once warm up. Takes lazy loading out of the equation and ensures we
+    // created the graphs properly.
+    validate(springFactory);
+    validate(juiceFactory);
+    validate(byHandFactory);
+
+    for (int i2 = 0; i2 < 10; i2++) {
+      iterate(springFactory, "Spring:  ");
+      iterate(juiceFactory,  "Guice:   ");
+      iterate(byHandFactory, "By Hand: ");
+
+      System.err.println();
+    }
+
+    System.err.println("Concurrent:");
+
+    for (int i2 = 0; i2 < 10; i2++) {
+      concurrentlyIterate(springFactory, "Spring:  ");
+      concurrentlyIterate(juiceFactory,  "Guice:   ");
+      concurrentlyIterate(byHandFactory, "By Hand: ");
+
+      System.err.println();
+    }
+  }
+
+  static final Callable<Foo> springFactory = new Callable<Foo>() {
+
+    final DefaultListableBeanFactory beanFactory;
+
+    {
+      beanFactory = new DefaultListableBeanFactory();
+
+      RootBeanDefinition tee = new RootBeanDefinition(TeeImpl.class, true);
+      tee.setLazyInit(true);
+      ConstructorArgumentValues teeValues = new ConstructorArgumentValues();
+      teeValues.addGenericArgumentValue("test");
+      tee.setConstructorArgumentValues(teeValues);
+
+      RootBeanDefinition bar = new RootBeanDefinition(BarImpl.class, false);
+      ConstructorArgumentValues barValues = new ConstructorArgumentValues();
+      barValues.addGenericArgumentValue(new RuntimeBeanReference("tee"));
+      barValues.addGenericArgumentValue(5);
+      bar.setConstructorArgumentValues(barValues);
+
+      RootBeanDefinition foo = new RootBeanDefinition(Foo.class, false);
+      MutablePropertyValues fooValues = new MutablePropertyValues();
+      fooValues.addPropertyValue("i", 5);
+      fooValues.addPropertyValue("bar", new RuntimeBeanReference("bar"));
+      fooValues.addPropertyValue("copy", new RuntimeBeanReference("bar"));
+      fooValues.addPropertyValue("s", "test");
+      foo.setPropertyValues(fooValues);
+
+      beanFactory.registerBeanDefinition("foo", foo);
+      beanFactory.registerBeanDefinition("bar", bar);
+      beanFactory.registerBeanDefinition("tee", tee);
+    }
+
+    public Foo call() throws Exception {
+      return (Foo) beanFactory.getBean("foo");
+    }
+  };
+
+  static final Callable<Foo> juiceFactory = new Callable<Foo>() {
+    final Provider<Foo> fooProvider;
+    {
+      Injector injector;
+      try {
+        injector = Guice.createInjector(new AbstractModule() {
+          protected void configure() {
+            bind(Tee.class).to(TeeImpl.class);
+            bind(Bar.class).to(BarImpl.class);
+            bind(Foo.class);
+            bindConstant().annotatedWith(I.class).to(5);
+            bindConstant().annotatedWith(S.class).to("test");
+          }
+        });
+      } catch (CreationException e) {
+        throw new RuntimeException(e);
+      }
+      fooProvider = injector.getProvider(Foo.class);
+    }
+
+    public Foo call() throws Exception {
+      return fooProvider.get();
+    }
+  };
+
+  static final Callable<Foo> byHandFactory = new Callable<Foo>() {
+    final Tee tee = new TeeImpl("test");
+    public Foo call() throws Exception {
+      Foo foo = new Foo();
+      foo.setI(5);
+      foo.setS("test");
+      Bar bar = new BarImpl(tee, 5);
+      Bar copy = new BarImpl(tee, 5);
+      foo.setBar(bar);
+      foo.setCopy(copy);
+      return foo;
+    }
+  };
+
+  static void validate(Callable<Foo> t) throws Exception {
+    Foo foo = t.call();
+    assertEquals(5, foo.i);
+    assertEquals("test", foo.s);
+    assertSame(foo.bar.getTee(), foo.copy.getTee());
+    assertEquals(5, foo.bar.getI());
+    assertEquals("test", foo.bar.getTee().getS());
+  }
+
+  static final DecimalFormat format = new DecimalFormat();
+
+  static void iterate(Callable<Foo> callable, String label) {
+    int count = 100000;
+
+    long time = System.currentTimeMillis();
+
+    for (int i = 0; i < count; i++) {
+      try {
+        callable.call();
+      }
+      catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+    }
+
+    time = System.currentTimeMillis() - time;
+
+    System.err.println(label
+        + format.format(count * 1000 / time) + " creations/s");
+  }
+
+  static void concurrentlyIterate(final Callable<Foo> callable, String label) {
+    int threadCount = 10;
+    final int count = 10000;
+
+    Thread[] threads = new Thread[threadCount];
+
+    for (int i = 0; i < threadCount; i++) {
+      threads[i] = new Thread() {
+        public void run() {
+          for (int i = 0; i < count; i++) {
+            try {
+              validate(callable);
+            }
+            catch (Exception e) {
+              throw new RuntimeException(e);
+            }
+          }
+        }
+      };
+    }
+
+
+    long time = System.currentTimeMillis();
+
+    for (int i = 0; i < threadCount; i++) {
+      threads[i].start();
+    }
+
+    for (int i = 0; i < threadCount; i++) {
+      try {
+        threads[i].join();
+      }
+      catch (InterruptedException e) {
+        throw new RuntimeException(e);
+      }
+    }
+
+    time = System.currentTimeMillis() - time;
+
+    System.err.println(label
+        + format.format(count * 1000 / time) + " creations/s");
+  }
+
+  public static class Foo {
+
+    Bar bar;
+    Bar copy;
+    String s;
+    int i;
+
+    @Inject
+    public void setI(@I int i) {
+      this.i = i;
+    }
+
+    @Inject
+    public void setBar(Bar bar) {
+      this.bar = bar;
+    }
+
+    @Inject
+    public void setCopy(Bar copy) {
+      this.copy = copy;
+    }
+
+    @Inject
+    public void setS(@S String s) {
+      this.s = s;
+    }
+  }
+
+  interface Bar {
+
+    Tee getTee();
+    int getI();
+  }
+
+  public static class BarImpl implements Bar {
+
+    final int i;
+    final Tee tee;
+
+    @Inject
+    public BarImpl(Tee tee, @I int i) {
+      this.tee = tee;
+      this.i = i;
+    }
+
+    public Tee getTee() {
+      return tee;
+    }
+
+    public int getI() {
+      return i;
+    }
+  }
+
+  interface Tee {
+
+    String getS();
+  }
+
+  @Singleton
+  public static class TeeImpl implements Tee {
+
+    final String s;
+
+    @Inject
+    public TeeImpl(@S String s) {
+      this.s = s;
+    }
+
+    public String getS() {
+      return s;
+    }
+  }
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface I {}
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface S {}
+}
diff --git a/core/test/com/google/inject/PrivateModuleTest.java b/core/test/com/google/inject/PrivateModuleTest.java
new file mode 100644
index 0000000..05db62b
--- /dev/null
+++ b/core/test/com/google/inject/PrivateModuleTest.java
@@ -0,0 +1,564 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.inject.Asserts.asModuleChain;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.ExposedBinding;
+import com.google.inject.spi.PrivateElements;
+import com.google.inject.util.Types;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class PrivateModuleTest extends TestCase {
+
+  public void testBasicUsage() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).annotatedWith(named("a")).toInstance("public");
+
+        install(new PrivateModule() {
+          @Override public void configure() {
+            bind(String.class).annotatedWith(named("b")).toInstance("i");
+
+            bind(AB.class).annotatedWith(named("one")).to(AB.class);
+            expose(AB.class).annotatedWith(named("one"));
+          }
+        });
+
+        install(new PrivateModule() {
+          @Override public void configure() {
+            bind(String.class).annotatedWith(named("b")).toInstance("ii");
+
+            bind(AB.class).annotatedWith(named("two")).to(AB.class);
+            expose(AB.class).annotatedWith(named("two"));
+          }
+        });
+      }
+    });
+
+    AB ab1 = injector.getInstance(Key.get(AB.class, named("one")));
+    assertEquals("public", ab1.a);
+    assertEquals("i", ab1.b);
+
+    AB ab2 = injector.getInstance(Key.get(AB.class, named("two")));
+    assertEquals("public", ab2.a);
+    assertEquals("ii", ab2.b);
+  }
+  
+  public void testWithoutPrivateModules() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        PrivateBinder bindA = binder().newPrivateBinder();
+        bindA.bind(String.class).annotatedWith(named("a")).toInstance("i");
+        bindA.expose(String.class).annotatedWith(named("a"));
+        bindA.bind(String.class).annotatedWith(named("c")).toInstance("private to A");
+
+        PrivateBinder bindB = binder().newPrivateBinder();
+        bindB.bind(String.class).annotatedWith(named("b")).toInstance("ii");
+        bindB.expose(String.class).annotatedWith(named("b"));
+        bindB.bind(String.class).annotatedWith(named("c")).toInstance("private to B");
+      }
+    });
+
+    assertEquals("i", injector.getInstance(Key.get(String.class, named("a"))));
+    assertEquals("ii", injector.getInstance(Key.get(String.class, named("b"))));
+  }
+
+  public void testMisplacedExposedAnnotation() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {}
+
+        @Provides @Exposed
+        String provideString() {
+          return "i";
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ",
+          "Exposed bindings are only applicable to private binders.",
+          " at " + PrivateModuleTest.class.getName(), "provideString(PrivateModuleTest.java:");
+    }
+  }
+
+  public void testMisplacedExposeStatement() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          ((PrivateBinder) binder()).expose(String.class).annotatedWith(named("a"));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ",
+          "Exposed bindings are only applicable to private binders.",
+          " at " + PrivateModuleTest.class.getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  public void testPrivateModulesAndProvidesMethods() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        install(new PrivateModule() {
+          @Override public void configure() {
+            expose(String.class).annotatedWith(named("a"));
+          }
+
+          @Provides @Named("a") String providePublicA() {
+            return "i";
+          }
+
+          @Provides @Named("b") String providePrivateB() {
+            return "private";
+          }
+        });
+
+        install(new PrivateModule() {
+          @Override public void configure() {}
+
+          @Provides @Named("c") String providePrivateC() {
+            return "private";
+          }
+
+          @Provides @Exposed @Named("d") String providePublicD() {
+            return "ii";
+          }
+        });
+      }
+    });
+
+    assertEquals("i", injector.getInstance(Key.get(String.class, named("a"))));
+
+    try {
+      injector.getInstance(Key.get(String.class, named("b")));
+      fail();
+    } catch(ConfigurationException expected) {
+    }
+
+    try {
+      injector.getInstance(Key.get(String.class, named("c")));
+      fail();
+    } catch(ConfigurationException expected) {
+    }
+
+    assertEquals("ii", injector.getInstance(Key.get(String.class, named("d"))));
+  }
+
+  public void testCannotBindAKeyExportedByASibling() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          install(new PrivateModule() {
+            @Override public void configure() {
+              bind(String.class).toInstance("public");
+              expose(String.class);
+            }
+          });
+
+          install(new PrivateModule() {
+            @Override public void configure() {
+              bind(String.class).toInstance("private");
+            }
+          });
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "A binding to java.lang.String was already configured at ",
+          getClass().getName(), getDeclaringSourcePart(getClass()),
+          " at " + getClass().getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  public void testExposeButNoBind() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(String.class).annotatedWith(named("a")).toInstance("a");
+          bind(String.class).annotatedWith(named("b")).toInstance("b");
+
+          install(new PrivateModule() {
+            @Override public void configure() {
+              expose(AB.class);
+            }
+          });
+        }
+      });
+      fail("AB was exposed but not bound");
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Could not expose() " + AB.class.getName() + ", it must be explicitly bound",
+          getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  /**
+   * Ensure that when we've got errors in different private modules, Guice presents all errors
+   * in a unified message.
+   */
+  public void testMessagesFromPrivateModulesAreNicelyIntegrated() {
+    try {
+      Guice.createInjector(
+          new PrivateModule() {
+            @Override public void configure() {
+              bind(C.class);
+            }
+          },
+          new PrivateModule() {
+            @Override public void configure() {
+              bind(AB.class);
+            }
+          }
+      );
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for " + C.class.getName() + " was bound.",
+          "at " + getClass().getName(), getDeclaringSourcePart(getClass()),
+          "2) No implementation for " + String.class.getName(), "Named(value=a) was bound.",
+          "for field at " + AB.class.getName() + ".a(PrivateModuleTest.java:",
+          "3) No implementation for " + String.class.getName(), "Named(value=b) was bound.",
+          "for field at " + AB.class.getName() + ".b(PrivateModuleTest.java:",
+          "3 errors");
+    }
+  }
+
+  public void testNestedPrivateInjectors() {
+    Injector injector = Guice.createInjector(new PrivateModule() {
+      @Override public void configure() {
+        expose(String.class);
+
+        install(new PrivateModule() {
+          @Override public void configure() {
+            bind(String.class).toInstance("nested");
+            expose(String.class);
+          }
+        });
+      }
+    });
+
+    assertEquals("nested", injector.getInstance(String.class));
+  }
+
+  public void testInstallingRegularModulesFromPrivateModules() {
+    Injector injector = Guice.createInjector(new PrivateModule() {
+      @Override public void configure() {
+        expose(String.class);
+
+        install(new AbstractModule() {
+          @Override protected void configure() {
+            bind(String.class).toInstance("nested");
+          }
+        });
+      }
+    });
+
+    assertEquals("nested", injector.getInstance(String.class));
+  }
+
+  public void testNestedPrivateModulesWithSomeKeysUnexposed() {
+    Injector injector = Guice.createInjector(new PrivateModule() {
+      @Override public void configure() {
+        bind(String.class).annotatedWith(named("bound outer, exposed outer")).toInstance("boeo");
+        expose(String.class).annotatedWith(named("bound outer, exposed outer"));
+        bind(String.class).annotatedWith(named("bound outer, exposed none")).toInstance("boen");
+        expose(String.class).annotatedWith(named("bound inner, exposed both"));
+
+        install(new PrivateModule() {
+          @Override public void configure() {
+            bind(String.class).annotatedWith(named("bound inner, exposed both")).toInstance("bieb");
+            expose(String.class).annotatedWith(named("bound inner, exposed both"));
+            bind(String.class).annotatedWith(named("bound inner, exposed none")).toInstance("bien");
+          }
+        });
+      }
+    });
+
+    assertEquals("boeo",
+        injector.getInstance(Key.get(String.class, named("bound outer, exposed outer"))));
+    assertEquals("bieb",
+        injector.getInstance(Key.get(String.class, named("bound inner, exposed both"))));
+
+    try {
+      injector.getInstance(Key.get(String.class, named("bound outer, exposed none")));
+      fail();
+    } catch (ConfigurationException expected) {
+    }
+
+    try {
+      injector.getInstance(Key.get(String.class, named("bound inner, exposed none")));
+      fail();
+    } catch (ConfigurationException expected) {
+    }
+  }
+
+  public void testDependenciesBetweenPrivateAndPublic() {
+    Injector injector = Guice.createInjector(
+        new PrivateModule() {
+          @Override protected void configure() {}
+
+          @Provides @Exposed @Named("a") String provideA() {
+            return "A";
+          }
+
+          @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
+            return ab + "C";
+          }
+        },
+        new AbstractModule() {
+          @Override protected void configure() {}
+
+          @Provides @Named("ab") String provideAb(@Named("a") String a) {
+            return a + "B";
+          }
+
+          @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
+            return abc + "D";
+          }
+        }
+    );
+
+    assertEquals("ABCD", injector.getInstance(Key.get(String.class, named("abcd"))));
+  }
+
+  public void testDependenciesBetweenPrivateAndPublicWithPublicEagerSingleton() {
+    Injector injector = Guice.createInjector(
+        new PrivateModule() {
+          @Override protected void configure() {}
+
+          @Provides @Exposed @Named("a") String provideA() {
+            return "A";
+          }
+
+          @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
+            return ab + "C";
+          }
+        },
+        new AbstractModule() {
+          @Override protected void configure() {
+            bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider<String>() {
+              @Inject @Named("abcd") String abcd;
+
+              public String get() {
+                return abcd + "E";
+              }
+            }).asEagerSingleton();
+          }
+
+          @Provides @Named("ab") String provideAb(@Named("a") String a) {
+            return a + "B";
+          }
+
+          @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
+            return abc + "D";
+          }
+        }
+    );
+
+    assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde"))));
+  }
+
+  public void testDependenciesBetweenPrivateAndPublicWithPrivateEagerSingleton() {
+    Injector injector = Guice.createInjector(
+        new AbstractModule() {
+          @Override protected void configure() {}
+
+          @Provides @Named("ab") String provideAb(@Named("a") String a) {
+            return a + "B";
+          }
+
+          @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
+            return abc + "D";
+          }
+        },
+        new PrivateModule() {
+          @Override protected void configure() {
+            bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider<String>() {
+              @Inject @Named("abcd") String abcd;
+
+              public String get() {
+                return abcd + "E";
+              }
+            }).asEagerSingleton();
+            expose(String.class).annotatedWith(named("abcde"));
+          }
+
+          @Provides @Exposed @Named("a") String provideA() {
+            return "A";
+          }
+
+          @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
+            return ab + "C";
+          }
+        }
+    );
+
+    assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde"))));
+  }
+
+  static class AB {
+    @Inject @Named("a") String a;
+    @Inject @Named("b") String b;
+  }
+
+  interface C {}
+
+  public void testSpiAccess() {
+    Injector injector = Guice.createInjector(new PrivateModule() {
+          @Override public void configure() {
+            bind(String.class).annotatedWith(named("a")).toInstance("private");
+            bind(String.class).annotatedWith(named("b")).toInstance("exposed");
+            expose(String.class).annotatedWith(named("b"));
+          }
+        });
+
+    ExposedBinding<?> binding
+        = (ExposedBinding<?>) injector.getBinding(Key.get(String.class, Names.named("b")));
+    assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class))),
+        binding.getDependencies());
+    PrivateElements privateElements = binding.getPrivateElements();
+    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class, named("b"))),
+        privateElements.getExposedKeys());
+    assertContains(privateElements.getExposedSource(Key.get(String.class, named("b"))).toString(),
+        PrivateModuleTest.class.getName(), getDeclaringSourcePart(getClass()));
+    Injector privateInjector = privateElements.getInjector();
+    assertEquals("private", privateInjector.getInstance(Key.get(String.class, Names.named("a"))));
+  }
+  
+  public void testParentBindsSomethingInPrivate() {
+    try {
+      Guice.createInjector(new FailingModule());
+      fail();
+    } catch(CreationException expected) {
+      assertEquals(1, expected.getErrorMessages().size());
+      assertContains(expected.toString(),
+          "Unable to create binding for java.util.List.",
+          "It was already configured on one or more child injectors or private modules",
+          "bound at " + FailingPrivateModule.class.getName() + ".configure(",
+          asModuleChain(FailingModule.class, ManyPrivateModules.class, FailingPrivateModule.class),
+          "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(",
+          asModuleChain(
+              FailingModule.class, ManyPrivateModules.class, SecondFailingPrivateModule.class),
+          "If it was in a PrivateModule, did you forget to expose the binding?",
+          "at " + FailingModule.class.getName() + ".configure(");
+    }
+  }
+  
+  public void testParentBindingToPrivateLinkedJitBinding() {
+    Injector injector = Guice.createInjector(new ManyPrivateModules());
+    try {
+      injector.getBinding(Key.get(Types.providerOf(List.class)));
+      fail();
+    } catch(ConfigurationException expected) {
+      assertEquals(1, expected.getErrorMessages().size());
+      assertContains(expected.toString(),
+          "Unable to create binding for com.google.inject.Provider<java.util.List>.",
+          "It was already configured on one or more child injectors or private modules",
+          "bound at " + FailingPrivateModule.class.getName() + ".configure(",
+          asModuleChain(ManyPrivateModules.class, FailingPrivateModule.class),
+          "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(",
+          asModuleChain(ManyPrivateModules.class, SecondFailingPrivateModule.class),
+          "If it was in a PrivateModule, did you forget to expose the binding?",
+          "while locating com.google.inject.Provider<java.util.List>");
+    }
+  }
+  
+  public void testParentBindingToPrivateJitBinding() {
+    Injector injector = Guice.createInjector(new ManyPrivateModules());
+    try {
+      injector.getBinding(PrivateFoo.class);
+      fail();
+    } catch(ConfigurationException expected) {
+      assertEquals(1, expected.getErrorMessages().size());
+      assertContains(expected.toString(),
+          "Unable to create binding for " + PrivateFoo.class.getName(),
+          "It was already configured on one or more child injectors or private modules",
+          "(bound by a just-in-time binding)",
+          "If it was in a PrivateModule, did you forget to expose the binding?",
+          "while locating " + PrivateFoo.class.getName());
+    }
+  }
+
+  private static class FailingModule extends AbstractModule {
+    @Override protected void configure() {
+      bind(Collection.class).to(List.class);
+      install(new ManyPrivateModules());
+    }
+  }
+
+  private static class ManyPrivateModules extends AbstractModule {
+    @Override protected void configure() {
+      // make sure duplicate sources are collapsed
+      install(new FailingPrivateModule());
+      install(new FailingPrivateModule());
+      // but additional sources are listed
+      install(new SecondFailingPrivateModule());
+    }
+  }
+
+  private static class FailingPrivateModule extends PrivateModule {
+    @Override protected void configure() {
+      bind(List.class).toInstance(new ArrayList());
+      
+      // Add the Provider<List> binding, created just-in-time,
+      // to make sure our linked JIT bindings have the correct source.
+      getProvider(Key.get(Types.providerOf(List.class)));
+      
+      // Request a JIT binding for PrivateFoo, which can only
+      // be created in the private module because it depends
+      // on List.
+      getProvider(PrivateFoo.class);
+    }
+  }
+  
+  /** A second class, so we can see another name in the source list. */
+  private static class SecondFailingPrivateModule extends PrivateModule {
+    @Override protected void configure() {
+      bind(List.class).toInstance(new ArrayList());
+      
+      // Add the Provider<List> binding, created just-in-time,
+      // to make sure our linked JIT bindings have the correct source.
+      getProvider(Key.get(Types.providerOf(List.class)));
+      
+      // Request a JIT binding for PrivateFoo, which can only
+      // be created in the private module because it depends
+      // on List.
+      getProvider(PrivateFoo.class);
+    }
+  }
+  
+  private static class PrivateFoo {
+    @Inject List list;
+  } 
+}
diff --git a/core/test/com/google/inject/ProviderInjectionTest.java b/core/test/com/google/inject/ProviderInjectionTest.java
new file mode 100644
index 0000000..755ff97
--- /dev/null
+++ b/core/test/com/google/inject/ProviderInjectionTest.java
@@ -0,0 +1,187 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.name.Names.named;
+
+import com.google.inject.name.Named;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ProviderInjectionTest extends TestCase {
+
+  public void testProviderInjection() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Bar.class);
+        bind(SampleSingleton.class).in(Scopes.SINGLETON);
+      }
+    });
+
+    Foo foo = injector.getInstance(Foo.class);
+
+    Bar bar = foo.barProvider.get();
+    assertNotNull(bar);
+    assertNotSame(bar, foo.barProvider.get());
+
+    SampleSingleton singleton = foo.singletonProvider.get();
+    assertNotNull(singleton);
+    assertSame(singleton, foo.singletonProvider.get());
+  }
+
+  /** Test for bug 155. */
+  public void testProvidersAreInjectedWhenBound() {
+    Module m = new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Bar.class).toProvider(new Provider<Bar>() {
+          @SuppressWarnings("unused")
+          @Inject void cantBeCalled(Baz baz) {
+            fail("Can't have called this method since Baz is not bound.");
+          }
+          public Bar get() {
+            return new Bar() {};
+          }
+        });
+      }
+    };
+
+    try {
+      Guice.createInjector(m);
+      fail("Should have thrown a CreationException");
+    }
+    catch (CreationException expected) {
+    }
+  }
+
+  /**
+   * When custom providers are used at injector creation time, they should be
+   * injected before use. In this testcase, we verify that a provider for
+   * List.class is injected before it is used.
+   */
+  public void testProvidersAreInjectedBeforeTheyAreUsed() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      public void configure() {
+        // should bind String to "[true]"
+        bind(String.class).toProvider(new Provider<String>() {
+          private String value;
+          @Inject void initialize(List list) {
+            value = list.toString();
+          }
+          public String get() {
+            return value;
+          }
+        });
+
+        // should bind List to [true]
+        bind(List.class).toProvider(new Provider<List>() {
+          @Inject Boolean injectedYet = Boolean.FALSE;
+          public List get() {
+            return Arrays.asList(injectedYet);
+          }
+        });
+
+        // should bind Boolean to true
+        bind(Boolean.class).toInstance(Boolean.TRUE);
+      }
+    });
+
+    assertEquals("Providers not injected before use",
+        "[true]",
+        injector.getInstance(String.class));
+  }
+
+  /**
+   * This test ensures that regardless of binding order, instances are injected
+   * before they are used. It injects mutable Count objects and records their
+   * value at the time that they're injected.
+   */
+  public void testCreationTimeInjectionOrdering() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        // instance injection
+        bind(Count.class).annotatedWith(named("a")).toInstance(new Count(0) {
+          @Inject void initialize(@Named("b") Count bCount) {
+            value = bCount.value + 1;
+          }
+        });
+
+        // provider injection
+        bind(Count.class).annotatedWith(named("b")).toProvider(new Provider<Count>() {
+          Count count;
+          @Inject void initialize(@Named("c") Count cCount) {
+            count = new Count(cCount.value + 2);
+          }
+          public Count get() {
+            return count;
+          }
+        });
+
+        // field and method injection, fields first
+        bind(Count.class).annotatedWith(named("c")).toInstance(new Count(0) {
+          @Inject @Named("d") Count dCount;
+          @Inject void initialize(@Named("e") Count eCount) {
+            value = dCount.value + eCount.value + 4;
+          }
+        });
+
+        // static injection
+        requestStaticInjection(StaticallyInjectable.class);
+
+        bind(Count.class).annotatedWith(named("d")).toInstance(new Count(8));
+        bind(Count.class).annotatedWith(named("e")).toInstance(new Count(16));
+      }
+    });
+
+    assertEquals(28, injector.getInstance(Key.get(Count.class, named("c"))).value);
+    assertEquals(30, injector.getInstance(Key.get(Count.class, named("b"))).value);
+    assertEquals(31, injector.getInstance(Key.get(Count.class, named("a"))).value);
+    assertEquals(28, StaticallyInjectable.cCountAtInjectionTime);
+  }
+
+  static class Count {
+    int value;
+    Count(int value) {
+      this.value = value;
+    }
+  }
+
+  static class StaticallyInjectable {
+    static int cCountAtInjectionTime;
+    @Inject static void initialize(@Named("c") Count cCount) {
+      cCountAtInjectionTime = cCount.value;
+    }
+  }
+
+  static class Foo {
+    @Inject Provider<Bar> barProvider;
+    @Inject Provider<SampleSingleton> singletonProvider;
+  }
+
+  static class Bar {}
+
+  static class SampleSingleton {}
+
+  interface Baz { }
+
+}
diff --git a/core/test/com/google/inject/ProvisionExceptionTest.java b/core/test/com/google/inject/ProvisionExceptionTest.java
new file mode 100644
index 0000000..962794f
--- /dev/null
+++ b/core/test/com/google/inject/ProvisionExceptionTest.java
@@ -0,0 +1,352 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static com.google.inject.Asserts.reserialize;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class ProvisionExceptionTest extends TestCase {
+
+  public void testExceptionsCollapsed() {
+    try {
+      Guice.createInjector().getInstance(A.class);
+      fail(); 
+    } catch (ProvisionException e) {
+      assertTrue(e.getCause() instanceof UnsupportedOperationException);
+      assertContains(e.getMessage(), "Error injecting constructor",
+          "for parameter 0 at com.google.inject.ProvisionExceptionTest$C.setD",
+          "for field at com.google.inject.ProvisionExceptionTest$B.c",
+          "for parameter 0 at com.google.inject.ProvisionExceptionTest$A");
+    }
+  }
+
+  /**
+   * There's a pass-through of user code in the scope. We want exceptions thrown by Guice to be
+   * limited to a single exception, even if it passes through user code.
+   */
+  public void testExceptionsCollapsedWithScopes() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(B.class).in(Scopes.SINGLETON);
+        }
+      }).getInstance(A.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertTrue(e.getCause() instanceof UnsupportedOperationException);
+      assertFalse(e.getMessage().contains("custom provider"));
+      assertContains(e.getMessage(), "Error injecting constructor",
+          "for parameter 0 at com.google.inject.ProvisionExceptionTest$C.setD",
+          "for field at com.google.inject.ProvisionExceptionTest$B.c",
+          "for parameter 0 at com.google.inject.ProvisionExceptionTest$A");
+    }
+  }
+
+  public void testMethodInjectionExceptions() {
+    try {
+      Guice.createInjector().getInstance(E.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertTrue(e.getCause() instanceof UnsupportedOperationException);
+      assertContains(e.getMessage(), "Error injecting method",
+          "at " + E.class.getName() + ".setObject(ProvisionExceptionTest.java:");
+    }
+  }
+
+  public void testBindToProviderInstanceExceptions() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(D.class).toProvider(new DProvider());
+        }
+      }).getInstance(D.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertTrue(e.getCause() instanceof UnsupportedOperationException);
+      assertContains(e.getMessage(),
+          "1) Error in custom provider, java.lang.UnsupportedOperationException",
+          "at " + ProvisionExceptionTest.class.getName(),
+          getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  /**
+   * This test demonstrates that if the user throws a ProvisionException, we wrap it to add context.
+   */
+  public void testProvisionExceptionsAreWrappedForBindToType() {
+    try {
+      Guice.createInjector().getInstance(F.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(), "1) User Exception",
+          "at " + F.class.getName() + ".<init>(ProvisionExceptionTest.java:");
+    }
+  }
+
+  public void testProvisionExceptionsAreWrappedForBindToProviderType() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(F.class).toProvider(FProvider.class);
+        }
+      }).getInstance(F.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(), "1) User Exception",
+          "while locating ", FProvider.class.getName(),
+          "while locating ", F.class.getName());
+    }
+  }
+
+  public void testProvisionExceptionsAreWrappedForBindToProviderInstance() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(F.class).toProvider(new FProvider());
+        }
+      }).getInstance(F.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(), "1) User Exception",
+          "at " + ProvisionExceptionTest.class.getName(),
+          getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  public void testProvisionExceptionIsSerializable() throws IOException {
+    try {
+      Guice.createInjector().getInstance(A.class);
+      fail();
+    } catch (ProvisionException expected) {
+      ProvisionException reserialized = reserialize(expected);
+      assertContains(reserialized.getMessage(),
+          "1) Error injecting constructor, java.lang.UnsupportedOperationException",
+              "at com.google.inject.ProvisionExceptionTest$RealD.<init>()",
+              "at Key[type=com.google.inject.ProvisionExceptionTest$RealD, annotation=[none]]",
+              "@com.google.inject.ProvisionExceptionTest$C.setD()[0]",
+              "at Key[type=com.google.inject.ProvisionExceptionTest$C, annotation=[none]]",
+              "@com.google.inject.ProvisionExceptionTest$B.c",
+              "at Key[type=com.google.inject.ProvisionExceptionTest$B, annotation=[none]]",
+              "@com.google.inject.ProvisionExceptionTest$A.<init>()[0]",
+              "at Key[type=com.google.inject.ProvisionExceptionTest$A, annotation=[none]]");
+    }
+  }
+
+  public void testMultipleCauses() {
+    try {
+      Guice.createInjector().getInstance(G.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(),
+          "1) Error injecting method, java.lang.IllegalArgumentException",
+          "Caused by: java.lang.IllegalArgumentException: java.lang.UnsupportedOperationException",
+          "Caused by: java.lang.UnsupportedOperationException: Unsupported",
+          "2) Error injecting method, java.lang.NullPointerException: can't inject second either",
+          "Caused by: java.lang.NullPointerException: can't inject second either",
+          "2 errors");
+    }
+  }
+
+  public void testInjectInnerClass() throws Exception {
+    Injector injector = Guice.createInjector();
+    try {
+      injector.getInstance(InnerClass.class);
+      fail();
+    } catch (Exception expected) {
+      assertContains(expected.getMessage(),
+          "Injecting into inner classes is not supported.",
+          "while locating " + InnerClass.class.getName());
+    }
+  }
+
+  public void testInjectLocalClass() throws Exception {
+    class LocalClass {}
+
+    Injector injector = Guice.createInjector();
+    try {
+      injector.getInstance(LocalClass.class);
+      fail();
+    } catch (Exception expected) {
+      assertContains(expected.getMessage(),
+          "Injecting into inner classes is not supported.",
+          "while locating " + LocalClass.class.getName());
+    }
+  }
+
+  public void testBindingAnnotationsOnMethodsAndConstructors() {
+    try {
+      Injector injector = Guice.createInjector();
+      injector.getInstance(MethodWithBindingAnnotation.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), MethodWithBindingAnnotation.class.getName()
+          + ".injectMe() is annotated with @", Green.class.getName() + "(), ",
+          "but binding annotations should be applied to its parameters instead.",
+          "while locating " + MethodWithBindingAnnotation.class.getName());
+    }
+
+    try {
+      Guice.createInjector().getInstance(ConstructorWithBindingAnnotation.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), ConstructorWithBindingAnnotation.class.getName()
+          + ".<init>() is annotated with @", Green.class.getName() + "(), ",
+          "but binding annotations should be applied to its parameters instead.",
+          "at " + ConstructorWithBindingAnnotation.class.getName() + ".class",
+          "while locating " + ConstructorWithBindingAnnotation.class.getName());
+    }
+  }
+
+  public void testBindingAnnotationWarningForScala() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).annotatedWith(Green.class).toInstance("lime!");
+      }
+    });
+    injector.getInstance(LikeScala.class);
+  }
+
+  public void testLinkedBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(D.class).to(RealD.class);
+      }
+    });
+
+    try {
+      injector.getInstance(D.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "at " + RealD.class.getName() + ".<init>(ProvisionExceptionTest.java:",
+          "while locating " + RealD.class.getName(),
+          "while locating " + D.class.getName());
+    }
+  }
+
+  public void testProviderKeyBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(D.class).toProvider(DProvider.class);
+      }
+    });
+
+    try {
+      injector.getInstance(D.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "while locating " + DProvider.class.getName(),
+          "while locating " + D.class.getName());
+    }
+  }
+
+  private class InnerClass {}
+
+  static class A {
+    @Inject
+    A(B b) { }
+  }
+  static class B {
+    @Inject C c;
+  }
+  static class C {
+    @Inject
+    void setD(RealD d) { }
+  }
+  static class E {
+    @Inject void setObject(Object o) {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  static class MethodWithBindingAnnotation {
+    @Inject @Green void injectMe(String greenString) {}
+  }
+
+  static class ConstructorWithBindingAnnotation {
+    // Suppress compiler errors by the error-prone checker InjectedConstructorAnnotations,
+    // which catches injected constructors with binding annotations.
+    @SuppressWarnings("InjectedConstructorAnnotations")
+    @Inject @Green ConstructorWithBindingAnnotation(String greenString) {}
+  }
+
+  /**
+   * In Scala, fields automatically get accessor methods with the same name. So we don't do
+   * misplaced-binding annotation detection if the offending method has a matching field.
+   */
+  static class LikeScala {
+    @Inject @Green String green;
+    @Inject @Green String green() { return green; }
+  }
+
+  @Retention(RUNTIME)
+  @Target({ FIELD, PARAMETER, CONSTRUCTOR, METHOD })
+  @BindingAnnotation
+  @interface Green {}
+
+  interface D {}
+
+  static class RealD implements D {
+    @Inject RealD() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  static class DProvider implements Provider<D> {
+    public D get() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  static class F {
+    @Inject public F() {
+      throw new ProvisionException("User Exception", new RuntimeException());
+    }
+  }
+
+  static class FProvider implements Provider<F> {
+    public F get() {
+      return new F();
+    }
+  }
+
+  static class G {
+    @Inject void injectFirst() {
+      throw new IllegalArgumentException(new UnsupportedOperationException("Unsupported"));
+    }
+    @Inject void injectSecond() {
+      throw new NullPointerException("can't inject second either");
+    }
+  }
+}
diff --git a/core/test/com/google/inject/ProvisionExceptionsTest.java b/core/test/com/google/inject/ProvisionExceptionsTest.java
new file mode 100644
index 0000000..23c323c
--- /dev/null
+++ b/core/test/com/google/inject/ProvisionExceptionsTest.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright (C) 2010 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.inject;
+
+import com.google.inject.internal.Errors;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+/**
+ * Tests that ProvisionExceptions are readable and clearly indicate to the user what went wrong with
+ * their code.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class ProvisionExceptionsTest extends TestCase {
+  
+  public void testConstructorRuntimeException() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindConstant().annotatedWith(Names.named("runtime")).to(true);
+        bind(Exploder.class).to(Explosion.class);
+        bind(Tracer.class).to(TracerImpl.class);        
+      }
+    });
+    try {
+      injector.getInstance(Tracer.class);
+      fail();
+    } catch(ProvisionException pe) {
+      // Make sure our initial error message gives the user exception.
+      Asserts.assertContains(pe.getMessage(),
+          "1) Error injecting constructor", "java.lang.IllegalStateException: boom!");
+      assertEquals(1, pe.getErrorMessages().size());
+      assertEquals(IllegalStateException.class, pe.getCause().getClass());
+      assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
+    }
+  }
+  
+  public void testConstructorCheckedException() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindConstant().annotatedWith(Names.named("runtime")).to(false);
+        bind(Exploder.class).to(Explosion.class);
+        bind(Tracer.class).to(TracerImpl.class);        
+      }
+    });
+    try {
+      injector.getInstance(Tracer.class);
+      fail();
+    } catch(ProvisionException pe) {
+      // Make sure our initial error message gives the user exception.
+      Asserts.assertContains(pe.getMessage(),
+          "1) Error injecting constructor", "java.io.IOException: boom!");
+      assertEquals(1, pe.getErrorMessages().size());
+      assertEquals(IOException.class, pe.getCause().getClass());
+      assertEquals(IOException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
+    }
+  }
+  
+  public void testCustomProvidersRuntimeException() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Exploder.class).toProvider(new Provider<Exploder>() {
+          public Exploder get() {
+            return Explosion.createRuntime();
+          }
+        });
+        bind(Tracer.class).to(TracerImpl.class);        
+      }
+    });
+    try {
+      injector.getInstance(Tracer.class);
+      fail();
+    } catch(ProvisionException pe) {
+      // Make sure our initial error message gives the user exception.
+      Asserts.assertContains(pe.getMessage(),
+          "1) Error in custom provider", "java.lang.IllegalStateException: boom!");
+      assertEquals(1, pe.getErrorMessages().size());
+      assertEquals(IllegalStateException.class, pe.getCause().getClass());
+      assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
+    }
+  }
+  
+  public void testProviderMethodRuntimeException() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Tracer.class).to(TracerImpl.class);        
+      }
+      @Provides Exploder exploder() {
+        return Explosion.createRuntime();
+      }
+    });
+    try {
+      injector.getInstance(Tracer.class);
+      fail();
+    } catch(ProvisionException pe) {
+      // Make sure our initial error message gives the user exception.
+      Asserts.assertContains(pe.getMessage(),
+          "1) Error in custom provider", "java.lang.IllegalStateException: boom!");
+      assertEquals(1, pe.getErrorMessages().size());
+      assertEquals(IllegalStateException.class, pe.getCause().getClass());
+      assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
+    }
+  }
+  
+  public void testProviderMethodCheckedException() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Tracer.class).to(TracerImpl.class);        
+      }
+      @Provides Exploder exploder() throws IOException {
+        return Explosion.createChecked();
+      }
+    });
+    try {
+      injector.getInstance(Tracer.class);
+      fail();
+    } catch(ProvisionException pe) {
+      pe.printStackTrace();
+      // Make sure our initial error message gives the user exception.
+      Asserts.assertContains(pe.getMessage(),
+          "1) Error in custom provider", "java.io.IOException: boom!");
+      assertEquals(1, pe.getErrorMessages().size());
+      assertEquals(IOException.class, pe.getCause().getClass());
+      assertEquals(IOException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
+    }
+  }
+  
+  private static interface Exploder {}
+  public static class Explosion implements Exploder {
+    @Inject public Explosion(@Named("runtime") boolean runtime) throws IOException {
+      if(runtime) {
+        throw new IllegalStateException("boom!");
+      } else {
+        throw new IOException("boom!");
+      }
+    }
+    
+    public static Explosion createRuntime() {
+      try {
+        return new Explosion(true);
+      } catch(IOException iox) {
+        throw new RuntimeException();
+      }      
+    }
+    
+    public static Explosion createChecked() throws IOException {
+      return new Explosion(false);
+    }
+  }
+  private static interface Tracer {}
+  private static class TracerImpl implements Tracer {
+    @Inject TracerImpl(Exploder explosion) {
+    }
+  }
+}
diff --git a/core/test/com/google/inject/ProvisionListenerTest.java b/core/test/com/google/inject/ProvisionListenerTest.java
new file mode 100644
index 0000000..6e1be84
--- /dev/null
+++ b/core/test/com/google/inject/ProvisionListenerTest.java
@@ -0,0 +1,796 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject;
+
+import static com.google.common.collect.ImmutableList.of;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.matcher.AbstractMatcher;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.name.Named;
+import com.google.inject.spi.DependencyAndSource;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.ProvisionListener;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests for {@link Binder#bindListener(Matcher, ProvisionListener...)}
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+// TODO(sameb): Add some tests for private modules & child injectors.
+public class ProvisionListenerTest extends TestCase {
+
+  public void testExceptionInListenerBeforeProvisioning() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), new FailBeforeProvision());
+      }
+    });
+    try {
+      injector.getInstance(Foo.class);
+      fail();
+    } catch(ProvisionException pe) {
+      assertEquals(1, pe.getErrorMessages().size());
+      assertContains(pe.getMessage(),
+          "1) Error notifying ProvisionListener " + FailBeforeProvision.class.getName()
+          + " of " + Foo.class.getName(),
+          "Reason: java.lang.RuntimeException: boo",
+          "while locating " + Foo.class.getName());
+      assertEquals("boo", pe.getCause().getMessage());
+    }
+  }
+  
+  public void testExceptionInListenerAfterProvisioning() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), new FailAfterProvision());
+      }
+    });
+    try {
+      injector.getInstance(Foo.class);
+      fail();
+    } catch(ProvisionException pe) {
+      assertEquals(1, pe.getErrorMessages().size());
+      assertContains(pe.getMessage(),
+          "1) Error notifying ProvisionListener " + FailAfterProvision.class.getName()
+          + " of " + Foo.class.getName(),
+          "Reason: java.lang.RuntimeException: boo",
+          "while locating " + Foo.class.getName());
+      assertEquals("boo", pe.getCause().getMessage());
+    }
+  }
+  
+  public void testExceptionInProvisionExplicitlyCalled() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), new JustProvision());
+      }
+    });
+    try {
+      injector.getInstance(FooBomb.class);
+      fail();
+    } catch(ProvisionException pe) {
+      assertEquals(1, pe.getErrorMessages().size());
+      assertContains(pe.getMessage(),
+          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
+          " at " + FooBomb.class.getName(),
+          " while locating " + FooBomb.class.getName());
+      assertEquals("Retry, Abort, Fail", pe.getCause().getMessage());
+    }
+  }
+  
+  public void testExceptionInProvisionAutomaticallyCalled() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), new NoProvision());
+      }
+    });
+    try {
+      injector.getInstance(FooBomb.class);
+      fail();
+    } catch(ProvisionException pe) {
+      assertEquals(1, pe.getErrorMessages().size());
+      assertContains(pe.getMessage(),
+          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
+          " at " + FooBomb.class.getName(),
+          " while locating " + FooBomb.class.getName());
+      assertEquals("Retry, Abort, Fail", pe.getCause().getMessage());
+    }
+  }
+  
+  public void testExceptionInFieldProvision() throws Exception {
+    final CountAndCaptureExceptionListener listener = new CountAndCaptureExceptionListener();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(new AbstractMatcher<Binding<?>>() {
+          @Override public boolean matches(Binding<?> binding) {
+            return binding.getKey().getRawType().equals(DependsOnFooBombInField.class);
+          }
+        }, listener);
+      }
+    });
+    assertEquals(0, listener.beforeProvision);
+    String expectedMsg = null;
+    try {
+      injector.getInstance(DependsOnFooBombInField.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertEquals(1, expected.getErrorMessages().size());
+      expectedMsg = expected.getMessage();
+      assertContains(listener.capture.get().getMessage(),
+          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
+          " at " + FooBomb.class.getName(),
+          " while locating " + FooBomb.class.getName(),
+          " while locating " + DependsOnFooBombInField.class.getName());
+    }
+    assertEquals(1, listener.beforeProvision);
+    assertEquals(expectedMsg, listener.capture.get().getMessage());
+    assertEquals(0, listener.afterProvision);
+  }
+  
+  public void testExceptionInCxtorProvision() throws Exception {
+    final CountAndCaptureExceptionListener listener = new CountAndCaptureExceptionListener();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(new AbstractMatcher<Binding<?>>() {
+          @Override public boolean matches(Binding<?> binding) {
+            return binding.getKey().getRawType().equals(DependsOnFooBombInCxtor.class);
+          }
+        }, listener);
+      }
+    });
+    assertEquals(0, listener.beforeProvision);
+    String expectedMsg = null;
+    try {
+      injector.getInstance(DependsOnFooBombInCxtor.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertEquals(1, expected.getErrorMessages().size());
+      expectedMsg = expected.getMessage();
+      assertContains(listener.capture.get().getMessage(),
+          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
+          " at " + FooBomb.class.getName(),
+          " while locating " + FooBomb.class.getName(),
+          " while locating " + DependsOnFooBombInCxtor.class.getName());
+    }
+    assertEquals(1, listener.beforeProvision);
+    assertEquals(expectedMsg, listener.capture.get().getMessage());
+    assertEquals(0, listener.afterProvision);
+  }
+
+  public void testListenerCallsProvisionTwice() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), new ProvisionTwice());
+      }
+    });
+    try {
+      injector.getInstance(Foo.class);
+      fail();
+    } catch(ProvisionException pe) {
+      assertEquals(1, pe.getErrorMessages().size());
+      assertContains(pe.getMessage(),
+          "1) Error notifying ProvisionListener " + ProvisionTwice.class.getName()
+          + " of " + Foo.class.getName(),
+          "Reason: java.lang.IllegalStateException: Already provisioned in this listener.",
+          "while locating " + Foo.class.getName());
+      assertEquals("Already provisioned in this listener.", pe.getCause().getMessage());  
+    }
+  }
+  
+  public void testCachedInScopePreventsProvisionNotify() {
+    final Counter count1 = new Counter();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), count1);
+        bind(Foo.class).in(Scopes.SINGLETON);
+      }
+    });
+    Foo foo = injector.getInstance(Foo.class);
+    assertNotNull(foo);
+    assertEquals(1, count1.count);
+    
+    // not notified the second time because nothing is provisioned
+    // (it's cached in the scope)
+    count1.count = 0;
+    assertSame(foo, injector.getInstance(Foo.class));
+    assertEquals(0, count1.count);
+  }
+  
+  public void testCombineAllBindListenerCalls() {
+    final Counter count1 = new Counter();
+    final Counter count2 = new Counter();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), count1);
+        bindListener(Matchers.any(), count2);
+      }
+    });
+    assertNotNull(injector.getInstance(Foo.class));
+    assertEquals(1, count1.count);
+    assertEquals(1, count2.count);
+  }
+  
+  public void testNotifyEarlyListenersIfFailBeforeProvision() {
+    final Counter count1 = new Counter();
+    final Counter count2 = new Counter();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), count1, new FailBeforeProvision(), count2);
+      }
+    });
+    try {
+      injector.getInstance(Foo.class);
+      fail();
+    } catch(ProvisionException pe) {
+      assertEquals(1, pe.getErrorMessages().size());
+      assertContains(pe.getMessage(),
+          "1) Error notifying ProvisionListener " + FailBeforeProvision.class.getName()
+          + " of " + Foo.class.getName(),
+          "Reason: java.lang.RuntimeException: boo",
+          "while locating " + Foo.class.getName());
+      assertEquals("boo", pe.getCause().getMessage());
+      
+      assertEquals(1, count1.count);
+      assertEquals(0, count2.count);
+    }
+  }
+  
+  public void testNotifyLaterListenersIfFailAfterProvision() {
+    final Counter count1 = new Counter();
+    final Counter count2 = new Counter();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), count1, new FailAfterProvision(), count2);
+      }
+    });
+    try {
+      injector.getInstance(Foo.class);
+      fail();
+    } catch(ProvisionException pe) {
+      assertEquals(1, pe.getErrorMessages().size());
+      assertContains(pe.getMessage(),
+          "1) Error notifying ProvisionListener " + FailAfterProvision.class.getName()
+          + " of " + Foo.class.getName(),
+          "Reason: java.lang.RuntimeException: boo",
+          "while locating " + Foo.class.getName());
+      assertEquals("boo", pe.getCause().getMessage());
+      
+      assertEquals(1, count1.count);
+      assertEquals(1, count2.count);
+    }
+  }
+  
+  public void testNotifiedKeysOfAllBindTypes() {
+    final Capturer capturer = new Capturer();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), capturer);
+        bind(Foo.class).annotatedWith(named("pk")).toProvider(FooP.class);
+        try {
+          bind(Foo.class).annotatedWith(named("cxtr")).toConstructor(Foo.class.getDeclaredConstructor());
+        } catch (Exception ex) {
+          throw new RuntimeException(ex);
+        }
+        bind(LinkedFoo.class).to(Foo.class);
+        bind(Interface.class).toInstance(new Implementation());
+        bindConstant().annotatedWith(named("constant")).to("MyConstant");
+      }
+      
+      @Provides @Named("pi") Foo provideFooBar() {
+        return new Foo();
+      }
+    });
+    
+    // toInstance & constant bindings are notified in random order, at the very beginning.
+    assertEquals(
+        ImmutableSet.of(Key.get(Interface.class), Key.get(String.class, named("constant"))),
+        capturer.getAsSetAndClear());
+    
+    // simple binding
+    assertNotNull(injector.getInstance(Foo.class));
+    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
+    
+    // provider key binding -- notifies about provider & the object, always
+    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pk"))));
+    assertEquals(of(Key.get(FooP.class), Key.get(Foo.class, named("pk"))), capturer.getAndClear());
+    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pk"))));
+    assertEquals(of(Key.get(FooP.class), Key.get(Foo.class, named("pk"))), capturer.getAndClear());
+    
+    // JIT provider key binding -- notifies about provider & the object, always
+    assertNotNull(injector.getInstance(JitFoo2.class));
+    assertEquals(of(Key.get(JitFoo2P.class), Key.get(JitFoo2.class)), capturer.getAndClear());
+    assertNotNull(injector.getInstance(JitFoo2.class));
+    assertEquals(of(Key.get(JitFoo2P.class), Key.get(JitFoo2.class)), capturer.getAndClear());
+    
+    // provider instance binding -- just the object (not the provider)
+    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pi"))));
+    assertEquals(of(Key.get(Foo.class, named("pi"))), capturer.getAndClear());
+    
+    // toConstructor binding
+    assertNotNull(injector.getInstance(Key.get(Foo.class, named("cxtr"))));
+    assertEquals(of(Key.get(Foo.class, named("cxtr"))), capturer.getAndClear());
+    
+    // linked binding -- notifies about the target (that's what's provisioned), not the link
+    assertNotNull(injector.getInstance(LinkedFoo.class));
+    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
+
+    // JIT linked binding -- notifies about the target (that's what's provisioned), not the link
+    assertNotNull(injector.getInstance(JitFoo.class));
+    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
+  }
+  
+  public void testSingletonMatcher() {
+    final Counter counter = new Counter();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(new AbstractMatcher<Binding<?>>() {
+          @Override
+          public boolean matches(Binding<?> t) {
+            return Scopes.isSingleton(t);
+          }
+        }, counter);
+      }
+    });
+    assertEquals(0, counter.count);
+    // no increment for getting Many.
+    injector.getInstance(Many.class);
+    assertEquals(0, counter.count);
+    // but an increment for getting Sole, since it's a singleton.
+    injector.getInstance(Sole.class);
+    assertEquals(1, counter.count);
+  }
+  
+  public void testCallingBindingDotGetProviderDotGet() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), new ProvisionListener() {
+          @Override
+          public <T> void onProvision(ProvisionInvocation<T> provision) {
+            provision.getBinding().getProvider().get(); // AGH!
+          }
+        });
+      }
+    });
+    
+    try {
+      injector.getInstance(Sole.class);
+      fail();
+    } catch(ProvisionException expected) {
+      // We don't really care what kind of error you get, we only care you get an error.
+    }
+    
+    try {
+      injector.getInstance(Many.class);
+      fail();
+    } catch(ProvisionException expected) {
+      // We don't really care what kind of error you get, we only care you get an error.
+    }
+  }
+  
+  interface Interface {}
+  class Implementation implements Interface {}
+  
+  @Singleton static class Sole {}
+  static class Many {}
+  
+  @ImplementedBy(Foo.class) static interface JitFoo {}  
+  @ProvidedBy(JitFoo2P.class) static class JitFoo2 {}  
+  static interface LinkedFoo {}
+  static class Foo implements JitFoo, LinkedFoo {}
+  static class FooP implements Provider<Foo> {
+    public Foo get() {
+      return new Foo();
+    }
+  }
+  static class JitFoo2P implements Provider<JitFoo2> {
+    public JitFoo2 get() {
+      return new JitFoo2();
+    }
+  }
+  
+  static class FooBomb {
+    FooBomb() {
+      throw new RuntimeException("Retry, Abort, Fail");
+    }
+  }
+  
+  static class DependsOnFooBombInField {
+    @Inject FooBomb fooBomb;
+  }
+  
+  static class DependsOnFooBombInCxtor {
+    @Inject DependsOnFooBombInCxtor(FooBomb fooBomb) {}
+  }
+  
+  private static class Counter implements ProvisionListener {
+    int count = 0;
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      count++;
+    }
+  }
+  
+  private static class CountAndCaptureExceptionListener implements ProvisionListener {
+    int beforeProvision = 0;
+    int afterProvision = 0;
+    AtomicReference<RuntimeException> capture = new AtomicReference<RuntimeException>();
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      beforeProvision++;
+      try {
+        provision.provision();
+      } catch (RuntimeException re) {
+        capture.set(re);
+        throw re;
+      }
+      afterProvision++;
+    }
+  }
+  
+  private static class Capturer implements ProvisionListener {
+    List<Key> keys = Lists.newArrayList(); 
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      keys.add(provision.getBinding().getKey());
+      T provisioned = provision.provision();
+      // InstanceBindings are the only kind of binding where the key can
+      // be an instanceof the provisioned, because it isn't linked to any
+      // direct implementation.  I guess maybe it'd also be possible
+      // with a toConstructor binding... but we don't use that in our tests.
+      if (provision.getBinding() instanceof InstanceBinding) {
+        Class<? super T> expected = provision.getBinding().getKey().getRawType();
+        assertTrue("expected instanceof: " + expected + ", but was: " + provisioned,
+            expected.isInstance(provisioned));
+      } else {
+        assertEquals(provision.getBinding().getKey().getRawType(), provisioned.getClass());
+      }
+    }
+    
+    Set<Key> getAsSetAndClear() {
+      Set<Key> copy = ImmutableSet.copyOf(keys);
+      keys.clear();
+      return copy;
+    }
+    
+    List<Key> getAndClear() {
+      List<Key> copy = ImmutableList.copyOf(keys);
+      keys.clear();
+      return copy;
+    }
+  }
+
+  private static class FailBeforeProvision implements ProvisionListener {
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      throw new RuntimeException("boo");
+    }
+  }  
+  private static class FailAfterProvision implements ProvisionListener {
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      provision.provision();
+      throw new RuntimeException("boo");
+    }
+  }  
+  private static class JustProvision implements ProvisionListener {
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      provision.provision();
+    }
+  }  
+  private static class NoProvision implements ProvisionListener {
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+    }
+  }
+  private static class ProvisionTwice implements ProvisionListener {
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      provision.provision();
+      provision.provision();
+    }
+  }
+  
+  private static class ChainAsserter implements ProvisionListener {
+    private final List<Class<?>> provisionList;
+    private final List<Class<?>> expected;
+    
+    public ChainAsserter(List<Class<?>> provisionList, Iterable<Class<?>> expected) {
+      this.provisionList = provisionList;
+      this.expected = ImmutableList.copyOf(expected);
+    }
+    
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      List<Class<?>> actual = Lists.newArrayList();
+      for (DependencyAndSource dep : provision.getDependencyChain()) {
+        actual.add(dep.getDependency().getKey().getRawType());
+      }
+      assertEquals(expected, actual);
+      provisionList.add(provision.getBinding().getKey().getRawType());
+    }
+  }
+  
+  private static Matcher<Binding<?>> keyMatcher(final Class<?> clazz) {
+    return new AbstractMatcher<Binding<?>>() {
+      @Override
+      public boolean matches(Binding<?> t) {
+        return t.getKey().equals(Key.get(clazz));
+      }
+    };
+  }
+  
+  @SuppressWarnings("unchecked")
+  public void testDependencyChain() {
+    final List<Class<?>> pList = Lists.newArrayList();
+    final List<Class<?>> totalList = Lists.newArrayList();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Instance.class).toInstance(new Instance());
+        bind(B.class).to(BImpl.class);
+        bind(D.class).toProvider(DP.class);
+        
+        bindListener(Matchers.any(), new ProvisionListener() {
+          public <T> void onProvision(ProvisionInvocation<T> provision) {
+            totalList.add(provision.getBinding().getKey().getRawType());
+          }
+        });
+        
+        // Build up a list of asserters for our dependency chains.
+        ImmutableList.Builder<Class<?>> chain = ImmutableList.builder();
+        chain.add(Instance.class);
+        bindListener(keyMatcher(Instance.class), new ChainAsserter(pList, chain.build()));
+        
+        chain.add(A.class);
+        bindListener(keyMatcher(A.class), new ChainAsserter(pList, chain.build()));
+        
+        chain.add(B.class).add(BImpl.class);
+        bindListener(keyMatcher(BImpl.class), new ChainAsserter(pList, chain.build()));
+        
+        chain.add(C.class);
+        bindListener(keyMatcher(C.class), new ChainAsserter(pList, chain.build()));
+        
+        // the chain has D before DP even though DP is provisioned & notified first
+        // because we do DP because of D, and need DP to provision D.
+        chain.add(D.class).add(DP.class);
+        bindListener(keyMatcher(D.class), new ChainAsserter(pList, chain.build()));
+        bindListener(keyMatcher(DP.class), new ChainAsserter(pList, chain.build()));
+        
+        chain.add(E.class);
+        bindListener(keyMatcher(E.class), new ChainAsserter(pList, chain.build()));
+        
+        chain.add(F.class);
+        bindListener(keyMatcher(F.class), new ChainAsserter(pList, chain.build()));
+      }
+      @Provides C c(D d) {
+        return new C() {};
+      }
+    });
+    Instance instance = injector.getInstance(Instance.class);
+    // make sure we're checking all of the chain asserters..
+    assertEquals(
+        of(Instance.class, A.class, BImpl.class, C.class, DP.class, D.class, E.class, F.class),
+        pList);
+    // and make sure that nothing else was notified that we didn't expect.
+    assertEquals(totalList, pList);
+  }
+  
+  public void testModuleRequestInjection() {
+    final AtomicBoolean notified = new AtomicBoolean();    
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        requestInjection(new Object() {
+          @Inject Foo foo;
+        });
+        bindListener(Matchers.any(),
+            new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified));
+      }
+    });
+    assertTrue(notified.get());
+  }
+  
+  public void testToProviderInstance() {
+    final AtomicBoolean notified = new AtomicBoolean();    
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Object.class).toProvider(new Provider<Object>() {
+          @Inject Foo foo;
+          public Object get() {
+            return null;
+          }
+        });
+        bindListener(Matchers.any(),
+            new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified));
+      }
+    });
+    assertTrue(notified.get());
+  }
+  
+  public void testInjectorInjectMembers() {
+    final Object object = new Object() {
+      @Inject Foo foo;
+    };
+    final AtomicBoolean notified = new AtomicBoolean();    
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(),
+            new SpecialChecker(Foo.class, object.getClass().getName(), notified));
+      }
+    }).injectMembers(object);
+    assertTrue(notified.get());
+  }
+  
+  private static class SpecialChecker implements ProvisionListener {
+    private final Class<?> notifyType;
+    private final String firstSource;
+    private final AtomicBoolean notified;
+    
+    public SpecialChecker(Class<?> notifyType, String firstSource, AtomicBoolean notified) {
+      this.notifyType = notifyType;
+      this.firstSource = firstSource;
+      this.notified = notified;
+    }
+    
+    public <T> void onProvision(ProvisionInvocation<T> provision) {
+      notified.set(true);
+      assertEquals(notifyType, provision.getBinding().getKey().getRawType());            
+      assertEquals(2, provision.getDependencyChain().size());
+      
+      assertNull(provision.getDependencyChain().get(0).getDependency());
+      assertContains(provision.getDependencyChain().get(0).getBindingSource(), firstSource);
+      
+      assertEquals(notifyType,
+          provision.getDependencyChain().get(1).getDependency().getKey().getRawType());
+      assertContains(provision.getDependencyChain().get(1).getBindingSource(),
+          notifyType.getName() + ".class(");
+    }
+  }
+  
+  private static class Instance {
+    @Inject A a;
+  }
+  private static class A {
+    @Inject A(B b) {}
+  }
+  private interface B {}
+  private static class BImpl implements B {
+    @Inject void inject(C c) {}
+  }
+  private interface C {}
+  private interface D {}
+  private static class DP implements Provider<D> {
+    @Inject Provider<E> ep;
+    public D get() {
+      ep.get();
+      return new D() {};
+    }
+  }
+  private static class E {
+    @SuppressWarnings("unused")
+    @Inject F f;
+  }
+  private static class F {
+  }
+
+  public void testBindToInjectorWithListeningGivesSaneException() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bindListener(Matchers.any(), new Counter());
+          bind(Injector.class).toProvider(Providers.<Injector>of(null));
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertContains(
+          ce.getMessage(), "Binding to core guice framework type is not allowed: Injector.");
+    }
+  }
+
+  public void testProvisionIsNotifiedAfterContextsClear() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), new ProvisionListener() {
+          @Override
+          public <T> void onProvision(ProvisionInvocation<T> provision) {
+            Object provisioned = provision.provision();
+            if (provisioned instanceof X) {
+              ((X)provisioned).init();
+            } else if (provisioned instanceof Y) {
+              X.createY = false;
+              ((Y)provisioned).init();
+            }
+          }
+        });
+      }
+    });
+
+    X.createY = true;
+    X x = injector.getInstance(X.class);
+    assertNotSame(x, x.y.x);
+    assertFalse("x.ID: " + x.ID + ", x.y.x.iD: " + x.y.x.ID, x.ID == x.y.x.ID);
+  }
+
+  private static class X {
+    final static AtomicInteger COUNTER = new AtomicInteger();
+    static boolean createY;
+
+    final int ID = COUNTER.getAndIncrement();
+    final Provider<Y> yProvider;
+    Y y;
+
+    @Inject X(Provider<Y> yProvider) {
+      this.yProvider = yProvider;
+    }
+
+    void init() {
+      if (createY) {
+        this.y = yProvider.get();
+      }
+    }
+  }
+
+  private static class Y {
+    final Provider<X> xProvider;
+    X x;
+
+    @Inject Y(Provider<X> xProvider) {
+      this.xProvider = xProvider;
+    }
+
+    void init() {
+      this.x = xProvider.get();
+    }
+  }
+  
+  public void testDeDuplicateProvisionListeners() {
+    final Counter counter = new Counter();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), counter);
+        bindListener(Matchers.any(), counter);
+      }
+    });
+    injector.getInstance(Many.class);
+    assertEquals("ProvisionListener not de-duplicated", 1, counter.count);
+  }
+}
diff --git a/core/test/com/google/inject/ReflectionTest.java b/core/test/com/google/inject/ReflectionTest.java
new file mode 100644
index 0000000..610f099
--- /dev/null
+++ b/core/test/com/google/inject/ReflectionTest.java
@@ -0,0 +1,85 @@
+/**
+ * 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 com.google.inject;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.spi.ElementSource;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ReflectionTest extends TestCase {
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface I {}
+
+  public void testNormalBinding() throws CreationException {
+    final Foo foo = new Foo();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class).toInstance(foo);
+      }
+    });
+
+    Binding<Foo> fooBinding = injector.getBinding(Key.get(Foo.class));
+    assertSame(foo, fooBinding.getProvider().get());
+    ElementSource source = (ElementSource) fooBinding.getSource();
+    assertNotNull(source.getDeclaringSource());
+    assertEquals(Key.get(Foo.class), fooBinding.getKey());
+  }
+
+  public void testConstantBinding() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindConstant().annotatedWith(I.class).to(5);
+      }
+    });
+
+    Binding<?> i = injector.getBinding(Key.get(int.class, I.class));
+    assertEquals(5, i.getProvider().get());
+    ElementSource source = (ElementSource) i.getSource();
+    assertNotNull(source.getDeclaringSource());
+    assertEquals(Key.get(int.class, I.class), i.getKey());
+  }
+
+  public void testLinkedBinding() throws CreationException {
+    final Bar bar = new Bar();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Bar.class).toInstance(bar);
+        bind(Key.get(Foo.class)).to(Key.get(Bar.class));
+      }
+    });
+
+    Binding<Foo> fooBinding = injector.getBinding(Key.get(Foo.class));
+    assertSame(bar, fooBinding.getProvider().get());
+    ElementSource source = (ElementSource) fooBinding.getSource();
+    assertNotNull(source.getDeclaringSource());
+    assertEquals(Key.get(Foo.class), fooBinding.getKey());
+  }
+
+  static class Foo {}
+
+  static class Bar extends Foo {}
+}
diff --git a/core/test/com/google/inject/RequestInjectionTest.java b/core/test/com/google/inject/RequestInjectionTest.java
new file mode 100644
index 0000000..dfd0f77
--- /dev/null
+++ b/core/test/com/google/inject/RequestInjectionTest.java
@@ -0,0 +1,235 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.TypeEncounter;
+import com.google.inject.spi.TypeListener;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class RequestInjectionTest extends TestCase {
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface ForField {}
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface ForMethod {}
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    HasInjections.staticField = 0;
+    HasInjections.staticMethod = null;
+  }
+
+  public void testInjectMembers() {
+    final HasInjections hi = new HasInjections();
+
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindConstant().annotatedWith(ForMethod.class).to("test");
+        bindConstant().annotatedWith(ForField.class).to(5);
+        requestInjection(hi);
+      }
+    });
+
+    assertEquals("test", hi.instanceMethod);
+    assertEquals(5, hi.instanceField);
+    assertNull(HasInjections.staticMethod);
+    assertEquals(0, HasInjections.staticField);
+  }
+
+  public void testInjectStatics() throws CreationException {
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindConstant().annotatedWith(ForMethod.class).to("test");
+        bindConstant().annotatedWith(ForField.class).to(5);
+        requestStaticInjection(HasInjections.class);
+      }
+    });
+
+    assertEquals("test", HasInjections.staticMethod);
+    assertEquals(5, HasInjections.staticField);
+  }
+  
+  public void testInjectMembersAndStatics() {
+    final HasInjections hi = new HasInjections();
+
+    Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindConstant().annotatedWith(ForMethod.class).to("test");
+        bindConstant().annotatedWith(ForField.class).to(5);
+        requestStaticInjection(HasInjections.class);
+        requestInjection(hi);
+      }
+    });
+
+    assertEquals("test", hi.instanceMethod);
+    assertEquals(5, hi.instanceField);
+    assertEquals("test", HasInjections.staticMethod);
+    assertEquals(5, HasInjections.staticField);
+  }
+
+  public void testValidationErrorOnInjectedMembers() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          requestInjection(new NeedsRunnable());
+        }
+      });
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for java.lang.Runnable was bound",
+          "at " + NeedsRunnable.class.getName(), ".runnable(RequestInjectionTest.java:");
+    }
+  }
+
+  public void testInjectionErrorOnInjectedMembers() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(Runnable.class).toProvider(new Provider<Runnable>() {
+            public Runnable get() {
+              throw new UnsupportedOperationException();
+            }
+          });
+          requestInjection(new NeedsRunnable());
+        }
+      });
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Error in custom provider, java.lang.UnsupportedOperationException",
+          "for field at " + NeedsRunnable.class.getName() + ".runnable(RequestInjectionTest.java:",
+          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  public void testUserExceptionWhileInjectingInstance() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          requestInjection(new BlowsUpOnInject());
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Error injecting method, java.lang.UnsupportedOperationException: Pop",
+          "at " + BlowsUpOnInject.class.getName() + ".injectInstance(RequestInjectionTest.java:");
+    }
+  }
+
+  public void testUserExceptionWhileInjectingStatically() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          requestStaticInjection(BlowsUpOnInject.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Error injecting method, java.lang.UnsupportedOperationException: Snap",
+          "at " + BlowsUpOnInject.class.getName() + ".injectStatically(RequestInjectionTest.java:");
+    }
+  }
+
+  static class NeedsRunnable {
+    @Inject Runnable runnable;
+  }
+
+  static class HasInjections {
+
+    @Inject @ForField static int staticField;
+    @Inject @ForField int instanceField;
+
+    static String staticMethod;
+    String instanceMethod;
+
+    @Inject static void setStaticMethod(@ForMethod String staticMethod) {
+      HasInjections.staticMethod = staticMethod;
+    }
+
+    @Inject void setInstanceS(@ForMethod String instanceS) {
+      this.instanceMethod = instanceS;
+    }
+  }
+
+  static class BlowsUpOnInject {
+    @Inject void injectInstance() {
+      throw new UnsupportedOperationException("Pop");
+    }
+
+    @Inject static void injectStatically() {
+      throw new UnsupportedOperationException("Snap");
+    }
+  }
+  
+  /*
+   * Tests that initializables of the same instance don't clobber
+   * membersInjectors in InitializableReference, so that they ultimately
+   * can be requested in any order.
+   */
+  public void testEarlyInjectableReferencesWithSameIdentity() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        // Add a listener to trigger all toInstance bindings to get an Initializable.
+        bindListener(Matchers.any(), new TypeListener() {
+          @Override
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+          }
+        });
+        
+        // Bind two different Keys to the IDENTITICAL object
+        // ORDER MATTERS! We want the String binding to push out the Object one
+        String fail = new String("better not fail!");
+        bind(Object.class).toInstance(fail);
+        bind(String.class).toInstance(fail);
+        
+        // Then try to inject those objects in a requestInjection,
+        // letting us get into InjectableReference.get before it has
+        // finished running through all its injections.
+        // Each of these technically has its own InjectableReference internally.
+        // ORDER MATTERS!.. because Object is injected first, that InjectableReference
+        // attempts to process its members injector, but it wasn't initialized,
+        // because String pushed it out of the queue!
+        requestInjection(new Object() {
+          @SuppressWarnings("unused") @Inject Object obj;
+          @SuppressWarnings("unused") @Inject String str;
+        });
+      }
+    });
+  }
+}
diff --git a/core/test/com/google/inject/RequireAtInjectOnConstructorsTest.java b/core/test/com/google/inject/RequireAtInjectOnConstructorsTest.java
new file mode 100644
index 0000000..e5f90c2
--- /dev/null
+++ b/core/test/com/google/inject/RequireAtInjectOnConstructorsTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2012 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.inject;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link Binder#requireAtInjectOnConstructors()}
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class RequireAtInjectOnConstructorsTest extends TestCase {
+  
+  public void testNoCxtors_explicitBinding() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(NoCxtors.class);
+          binder().requireAtInjectOnConstructors();
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      Asserts.assertContains(ce.getMessage(),
+          "1) Explicit @Inject annotations are required on constructors, but "
+          + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
+          "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
+    }
+  }
+  
+  public void testNoCxtors_jitBinding() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireAtInjectOnConstructors();
+      }
+    });
+    try {
+      injector.getInstance(NoCxtors.class);
+      fail();
+    } catch (ConfigurationException ce) {
+      Asserts.assertContains(ce.getMessage(),
+          "1) Explicit @Inject annotations are required on constructors, but "
+          + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
+          "while locating " + NoCxtors.class.getName());
+    }
+  }
+  
+  public void testNoCxtors_implicitBinding() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(Interface.class).to(NoCxtors.class);
+          binder().requireAtInjectOnConstructors();
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      Asserts.assertContains(ce.getMessage(),
+          "1) Explicit @Inject annotations are required on constructors, but "
+          + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
+          "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
+    }
+  }
+  
+  public void testNoCxtors_inheritedByPrivateModules() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireAtInjectOnConstructors();
+          install(new PrivateModule() {
+            @Override
+            protected void configure() {
+              bind(NoCxtors.class);
+            }
+          });
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      Asserts.assertContains(ce.getMessage(),
+          "1) Explicit @Inject annotations are required on constructors, but "
+          + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
+          "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
+    }
+  }
+  
+  public void testNoCxtors_accumulatesAllErrors() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(NoCxtors.class);
+          bind(AnotherNoCxtors.class);
+          binder().requireAtInjectOnConstructors();
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(2, ce.getErrorMessages().size());
+      Asserts.assertContains(ce.getMessage(),
+          "1) Explicit @Inject annotations are required on constructors, but "
+          + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
+          "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure",
+          "2) Explicit @Inject annotations are required on constructors, but "
+          + AnotherNoCxtors.class.getName() + " has no constructors annotated with @Inject",
+          "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
+    }
+  }
+  
+  public void testNoCxtors_separateOptionsForPrivateModules() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(AnotherNoCxtors.class);
+          install(new PrivateModule() {
+            @Override
+            protected void configure() {
+              binder().requireAtInjectOnConstructors();
+              bind(NoCxtors.class);
+            }
+          });
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      // This is testing that the parent module doesn't fail because it isn't included
+      // in the error message.
+      assertEquals(1, ce.getErrorMessages().size());
+      Asserts.assertContains(ce.getMessage(),
+          "1) Explicit @Inject annotations are required on constructors, but "
+          + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
+          "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
+    }
+  }
+  
+  public void testManyConstructorsButNoneWithAtInject() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(ManyConstructors.class);
+          binder().requireAtInjectOnConstructors();
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      Asserts.assertContains(ce.getMessage(),
+          "1) Explicit @Inject annotations are required on constructors, but "
+          + ManyConstructors.class.getName() + " has no constructors annotated with @Inject",
+          "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
+    }
+  }
+  
+  public void testRequireAtInjectStillAllowsToConstructorBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          try {
+            bind(ManyConstructors.class)
+                .toConstructor(ManyConstructors.class.getDeclaredConstructor());
+          } catch (Exception e) {
+            throw new RuntimeException(e);
+          }
+          binder().requireAtInjectOnConstructors();
+        }
+      });
+    injector.getInstance(ManyConstructors.class);
+  }
+  
+  private static interface Interface {}
+  private static class NoCxtors implements Interface {}  
+  private static class AnotherNoCxtors {}
+  private static class ManyConstructors {
+    @SuppressWarnings("unused") ManyConstructors() {}
+    @SuppressWarnings("unused") ManyConstructors(String a) {}
+    @SuppressWarnings("unused") ManyConstructors(int a) {}
+  }
+}
diff --git a/core/test/com/google/inject/ScopesTest.java b/core/test/com/google/inject/ScopesTest.java
new file mode 100644
index 0000000..15c2d2e
--- /dev/null
+++ b/core/test/com/google/inject/ScopesTest.java
@@ -0,0 +1,1192 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.asModuleChain;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static com.google.inject.name.Names.named;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.name.Named;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+import com.google.inject.spi.PrivateElements;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ScopesTest extends TestCase {
+
+  static final long DEADLOCK_TIMEOUT_SECONDS = 1;
+
+  private final AbstractModule singletonsModule = new AbstractModule() {
+    @Override protected void configure() {
+      bind(BoundAsSingleton.class).in(Scopes.SINGLETON);
+      bind(AnnotatedSingleton.class);
+      bind(EagerSingleton.class).asEagerSingleton();
+      bind(LinkedSingleton.class).to(RealLinkedSingleton.class);
+      bind(DependsOnJustInTimeSingleton.class);
+      bind(NotASingleton.class);
+      bind(ImplementedBySingleton.class).in(Scopes.SINGLETON);
+      bind(ProvidedBySingleton.class).in(Scopes.SINGLETON);
+    }
+  };
+
+  @Override protected void setUp() throws Exception {
+    AnnotatedSingleton.nextInstanceId = 0;
+    BoundAsSingleton.nextInstanceId = 0;
+    EagerSingleton.nextInstanceId = 0;
+    RealLinkedSingleton.nextInstanceId = 0;
+    JustInTimeSingleton.nextInstanceId = 0;
+    NotASingleton.nextInstanceId = 0;
+    Implementation.nextInstanceId = 0;
+    ProvidedBySingleton.nextInstanceId = 0;
+    ThrowingSingleton.nextInstanceId = 0;
+  }
+
+  public void testSingletons() {
+    Injector injector = Guice.createInjector(singletonsModule);
+
+    assertSame(
+        injector.getInstance(BoundAsSingleton.class),
+        injector.getInstance(BoundAsSingleton.class));
+
+    assertSame(
+        injector.getInstance(AnnotatedSingleton.class),
+        injector.getInstance(AnnotatedSingleton.class));
+
+    assertSame(
+        injector.getInstance(EagerSingleton.class),
+        injector.getInstance(EagerSingleton.class));
+
+    assertSame(
+        injector.getInstance(LinkedSingleton.class),
+        injector.getInstance(LinkedSingleton.class));
+
+    assertSame(
+        injector.getInstance(JustInTimeSingleton.class),
+        injector.getInstance(JustInTimeSingleton.class));
+
+    assertNotSame(
+        injector.getInstance(NotASingleton.class),
+        injector.getInstance(NotASingleton.class));
+
+    assertSame(
+        injector.getInstance(ImplementedBySingleton.class),
+        injector.getInstance(ImplementedBySingleton.class));
+
+    assertSame(
+        injector.getInstance(ProvidedBySingleton.class),
+        injector.getInstance(ProvidedBySingleton.class));
+  }
+
+  public void testJustInTimeAnnotatedSingleton() {
+    Injector injector = Guice.createInjector();
+
+    assertSame(
+        injector.getInstance(AnnotatedSingleton.class),
+        injector.getInstance(AnnotatedSingleton.class));
+  }
+
+  public void testSingletonIsPerInjector() {
+    assertNotSame(
+        Guice.createInjector().getInstance(AnnotatedSingleton.class),
+        Guice.createInjector().getInstance(AnnotatedSingleton.class));
+  }
+
+  public void testOverriddingAnnotation() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(AnnotatedSingleton.class).in(Scopes.NO_SCOPE);
+      }
+    });
+
+    assertNotSame(
+        injector.getInstance(AnnotatedSingleton.class),
+        injector.getInstance(AnnotatedSingleton.class));
+  }
+
+  public void testScopingAnnotationsOnAbstractTypeViaBind() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(A.class).to(AImpl.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          A.class.getName() + " is annotated with " + Singleton.class.getName(),
+          "but scope annotations are not supported for abstract types.",
+          "at " + A.class.getName() + ".class(ScopesTest.java:");
+    }
+  }
+
+  @Singleton
+  interface A {}
+  static class AImpl implements A {}
+
+  @Retention(RUNTIME)
+  @interface Component {}
+
+  @Component
+  @Singleton
+  interface ComponentAnnotationTest {}
+  static class ComponentAnnotationTestImpl implements ComponentAnnotationTest {}
+
+  public void testScopingAnnotationsOnAbstractTypeIsValidForComponent() {
+    Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(ComponentAnnotationTest.class).to(ComponentAnnotationTestImpl.class);
+      }
+    });
+  }
+
+  public void testScopingAnnotationsOnAbstractTypeViaImplementedBy() {
+    try {
+      Guice.createInjector().getInstance(D.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          D.class.getName() + " is annotated with " + Singleton.class.getName(),
+          "but scope annotations are not supported for abstract types.",
+          "at " + D.class.getName() + ".class(ScopesTest.java:");
+    }
+  }
+
+  @Singleton @ImplementedBy(DImpl.class)
+  interface D {}
+  static class DImpl implements D {}
+
+  public void testScopingAnnotationsOnAbstractTypeViaProvidedBy() {
+    try {
+      Guice.createInjector().getInstance(E.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          E.class.getName() + " is annotated with " + Singleton.class.getName(),
+          "but scope annotations are not supported for abstract types.",
+          "at " + E.class.getName() + ".class(ScopesTest.java:");
+    }
+  }
+
+  @Singleton @ProvidedBy(EProvider.class)
+  interface E {}
+  static class EProvider implements Provider<E> {
+    public E get() {
+      return null;
+    }
+  }
+
+  public void testScopeUsedButNotBound() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(B.class).in(CustomScoped.class);
+          bind(C.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No scope is bound to " + CustomScoped.class.getName(),
+          "at " + getClass().getName(), getDeclaringSourcePart(getClass()),
+          "2) No scope is bound to " + CustomScoped.class.getName(),
+          "at " + C.class.getName() + ".class");
+    }
+  }
+
+  static class B {}
+
+  @CustomScoped
+  static class C {}
+
+  public void testSingletonsInProductionStage() {
+    Guice.createInjector(Stage.PRODUCTION, singletonsModule);
+
+    assertEquals(1, AnnotatedSingleton.nextInstanceId);
+    assertEquals(1, BoundAsSingleton.nextInstanceId);
+    assertEquals(1, EagerSingleton.nextInstanceId);
+    assertEquals(1, RealLinkedSingleton.nextInstanceId);
+    assertEquals(1, JustInTimeSingleton.nextInstanceId);
+    assertEquals(0, NotASingleton.nextInstanceId);
+  }
+
+  public void testSingletonsInDevelopmentStage() {
+    Guice.createInjector(Stage.DEVELOPMENT, singletonsModule);
+
+    assertEquals(0, AnnotatedSingleton.nextInstanceId);
+    assertEquals(0, BoundAsSingleton.nextInstanceId);
+    assertEquals(1, EagerSingleton.nextInstanceId);
+    assertEquals(0, RealLinkedSingleton.nextInstanceId);
+    assertEquals(0, JustInTimeSingleton.nextInstanceId);
+    assertEquals(0, NotASingleton.nextInstanceId);
+  }
+
+  public void testSingletonScopeIsNotSerializable() throws IOException {
+    Asserts.assertNotSerializable(Scopes.SINGLETON);
+  }
+
+  public void testNoScopeIsNotSerializable() throws IOException {
+    Asserts.assertNotSerializable(Scopes.NO_SCOPE);
+  }
+
+  public void testUnscopedProviderWorksOutsideOfRequestedScope() {
+    final RememberProviderScope scope = new RememberProviderScope();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(CustomScoped.class, scope);
+        bind(List.class).to(ArrayList.class).in(CustomScoped.class);
+      }
+    });
+
+    injector.getInstance(List.class);
+    Provider<?> listProvider = scope.providers.get(Key.get(List.class));
+
+    // this line fails with a NullPointerException because the Providers
+    // passed to Scope.scope() don't work outside of the scope() method.
+    assertTrue(listProvider.get() instanceof ArrayList);
+  }
+
+  static class OuterRuntimeModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new InnerRuntimeModule());
+    }
+  }
+  static class InnerRuntimeModule extends AbstractModule {
+    @Override protected void configure() {
+      bindScope(NotRuntimeRetainedScoped.class, Scopes.NO_SCOPE);
+    }
+  }
+  public void testScopeAnnotationWithoutRuntimeRetention() {
+    try {
+      Guice.createInjector(new OuterRuntimeModule());
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Please annotate " + NotRuntimeRetainedScoped.class.getName()
+              + " with @Retention(RUNTIME).",
+          "at " + InnerRuntimeModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterRuntimeModule.class, InnerRuntimeModule.class));
+    }
+  }
+
+  static class OuterDeprecatedModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new InnerDeprecatedModule());
+    }
+  }
+  static class InnerDeprecatedModule extends AbstractModule {
+    @Override protected void configure() {
+      bindScope(Deprecated.class, Scopes.NO_SCOPE);
+    }
+  }
+  public void testBindScopeToAnnotationWithoutScopeAnnotation() {
+    try {
+      Guice.createInjector(new OuterDeprecatedModule());
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Please annotate " + Deprecated.class.getName() + " with @ScopeAnnotation.",
+          "at " + InnerDeprecatedModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterDeprecatedModule.class, InnerDeprecatedModule.class));
+    }
+  }
+
+  static class OuterScopeModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new CustomNoScopeModule());
+      install(new CustomSingletonModule());
+    }
+  }
+  static class CustomNoScopeModule extends AbstractModule {
+    @Override protected void configure() {
+      bindScope(CustomScoped.class, Scopes.NO_SCOPE);
+    }
+  }
+  static class CustomSingletonModule extends AbstractModule {
+    @Override protected void configure() {
+      bindScope(CustomScoped.class, Scopes.SINGLETON);
+    }
+  }
+
+  public void testBindScopeTooManyTimes() {
+    try {
+      Guice.createInjector(new OuterScopeModule());
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Scope Scopes.NO_SCOPE is already bound to " + CustomScoped.class.getName()
+              + " at " + CustomNoScopeModule.class.getName() + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterScopeModule.class, CustomNoScopeModule.class),
+          "Cannot bind Scopes.SINGLETON.",
+          "at " + ScopesTest.class.getName(), getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterScopeModule.class, CustomSingletonModule.class));
+    }
+  }
+
+  public void testBindDuplicateScope() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(CustomScoped.class, Scopes.SINGLETON);
+        bindScope(CustomScoped.class, Scopes.SINGLETON);
+      }
+    });
+
+    assertSame(
+        injector.getInstance(AnnotatedCustomScoped.class),
+        injector.getInstance(AnnotatedCustomScoped.class));
+  }
+
+  public void testDuplicateScopeAnnotations() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(CustomScoped.class, Scopes.NO_SCOPE);
+      }
+    });
+
+    try {
+      injector.getInstance(SingletonAndCustomScoped.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "1) More than one scope annotation was found: ",
+          "while locating " + SingletonAndCustomScoped.class.getName());
+    }
+  }
+
+  public void testNullScopedAsASingleton() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {}
+
+      final Iterator<String> values = Arrays.asList(null, "A").iterator();
+
+      @Provides @Singleton String provideString() {
+         return values.next();
+      }
+    });
+
+    assertNull(injector.getInstance(String.class));
+    assertNull(injector.getInstance(String.class));
+    assertNull(injector.getInstance(String.class));
+  }
+
+  class RememberProviderScope implements Scope {
+    final Map<Key<?>, Provider<?>> providers = Maps.newHashMap();
+    public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
+      providers.put(key, unscoped);
+      return unscoped;
+    }
+  }
+
+  public void testSingletonAnnotationOnParameterizedType() {
+    Injector injector = Guice.createInjector();
+    assertSame(injector.getInstance(new Key<Injected<String>>() {}),
+        injector.getInstance(new Key<Injected<String>>() {}));
+    assertSame(injector.getInstance(new Key<In<Integer>>() {}),
+        injector.getInstance(new Key<In<Short>>() {}));
+  }
+
+  @ImplementedBy(Injected.class) public interface In<T> {}
+  @Singleton public static class Injected<T>  implements In<T> {}
+
+  @Target({ ElementType.TYPE, ElementType.METHOD })
+  @Retention(RUNTIME)
+  @ScopeAnnotation
+  public @interface CustomScoped {}
+
+  static final Scope CUSTOM_SCOPE = new Scope() {
+    public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
+      return Scopes.SINGLETON.scope(key, unscoped);
+    }
+  };
+
+  @Target({ ElementType.TYPE, ElementType.METHOD })
+  @ScopeAnnotation
+  public @interface NotRuntimeRetainedScoped {}
+
+  @CustomScoped
+  static class AnnotatedCustomScoped {}
+
+  @Singleton
+  static class AnnotatedSingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+  }
+
+  static class BoundAsSingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+  }
+
+  static class EagerSingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+  }
+
+  interface LinkedSingleton {}
+
+  @Singleton
+  static class RealLinkedSingleton implements LinkedSingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+  }
+
+  static class DependsOnJustInTimeSingleton {
+    @Inject JustInTimeSingleton justInTimeSingleton;
+  }
+
+  @Singleton
+  static class JustInTimeSingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+  }
+
+  static class NotASingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+  }
+
+  @SuppressWarnings("MoreThanOneScopeAnnotationOnClass") // suppress compiler error for testing
+  @Singleton
+  @CustomScoped
+  static class SingletonAndCustomScoped {}
+
+  @ImplementedBy(Implementation.class)
+  static interface ImplementedBySingleton {}
+
+  @ProvidedBy(ImplementationProvider.class)
+  static class ProvidedBySingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+  }
+
+  static class Implementation implements ImplementedBySingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+  }
+
+  static class ImplementationProvider implements Provider<ProvidedBySingleton> {
+    public ProvidedBySingleton get() {
+      return new ProvidedBySingleton();
+    }
+  }
+
+  public void testScopeThatGetsAnUnrelatedObject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(B.class);
+        bind(C.class);
+        ProviderGetScope providerGetScope = new ProviderGetScope();
+        requestInjection(providerGetScope);
+        bindScope(CustomScoped.class, providerGetScope);
+      }
+    });
+
+    injector.getInstance(C.class);
+  }
+
+  class ProviderGetScope implements Scope {
+    @Inject Provider<B> bProvider;
+
+    public <T> Provider<T> scope(Key<T> key, final Provider<T> unscoped) {
+      return new Provider<T>() {
+        public T get() {
+          bProvider.get();
+          return unscoped.get();
+        }
+      };
+    }
+  }
+
+  public void testIsSingletonPositive() {
+    final Key<String> a = Key.get(String.class, named("A"));
+    final Key<String> b = Key.get(String.class, named("B"));
+    final Key<String> c = Key.get(String.class, named("C"));
+    final Key<String> d = Key.get(String.class, named("D"));
+    final Key<String> e = Key.get(String.class, named("E"));
+    final Key<String> f = Key.get(String.class, named("F"));
+    final Key<String> g = Key.get(String.class, named("G"));
+    final Key<Object> h = Key.get(Object.class, named("H"));
+    final Key<String> i = Key.get(String.class, named("I"));
+
+    Module singletonBindings = new AbstractModule() {
+      @Override protected void configure() {
+        bind(a).to(b);
+        bind(b).to(c);
+        bind(c).toProvider(Providers.of("c")).in(Scopes.SINGLETON);
+        bind(d).toInstance("d");
+        bind(e).toProvider(Providers.of("e")).asEagerSingleton();
+        bind(f).toProvider(Providers.of("f")).in(Singleton.class);
+        bind(h).to(AnnotatedSingleton.class);
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            bind(i).toProvider(Providers.of("i")).in(Singleton.class);
+            expose(i);
+          }
+        });
+      }
+
+      @Provides @Named("G") @Singleton String provideG() {
+        return "g";
+      }
+    };
+
+    @SuppressWarnings("unchecked") // we know the module contains only bindings
+    List<Element> moduleBindings = Elements.getElements(singletonBindings);
+    ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings);
+    assertFalse(Scopes.isSingleton(map.get(a))); // linked bindings are not followed by modules
+    assertFalse(Scopes.isSingleton(map.get(b)));
+    assertTrue(Scopes.isSingleton(map.get(c)));
+    assertTrue(Scopes.isSingleton(map.get(d)));
+    assertTrue(Scopes.isSingleton(map.get(e)));
+    assertTrue(Scopes.isSingleton(map.get(f)));
+    assertTrue(Scopes.isSingleton(map.get(g)));
+    assertFalse(Scopes.isSingleton(map.get(h))); // annotated classes are not followed by modules
+    assertTrue(Scopes.isSingleton(map.get(i)));
+
+    Injector injector = Guice.createInjector(singletonBindings);
+    assertTrue(Scopes.isSingleton(injector.getBinding(a)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(b)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(c)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(d)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(e)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(f)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(g)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(h)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(i)));
+  }
+
+  public void testIsSingletonNegative() {
+    final Key<String> a = Key.get(String.class, named("A"));
+    final Key<String> b = Key.get(String.class, named("B"));
+    final Key<String> c = Key.get(String.class, named("C"));
+    final Key<String> d = Key.get(String.class, named("D"));
+    final Key<String> e = Key.get(String.class, named("E"));
+    final Key<String> f = Key.get(String.class, named("F"));
+
+    Module singletonBindings = new AbstractModule() {
+      @Override protected void configure() {
+        bind(a).to(b);
+        bind(b).to(c);
+        bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE);
+        bind(d).toProvider(Providers.of("d")).in(CustomScoped.class);
+        bindScope(CustomScoped.class, Scopes.NO_SCOPE);
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            bind(f).toProvider(Providers.of("f")).in(CustomScoped.class);
+            expose(f);
+          }
+        });
+      }
+
+      @Provides @Named("E") @CustomScoped String provideE() {
+        return "e";
+      }
+    };
+
+    @SuppressWarnings("unchecked") // we know the module contains only bindings
+    List<Element> moduleBindings = Elements.getElements(singletonBindings);
+    ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings);
+    assertFalse(Scopes.isSingleton(map.get(a)));
+    assertFalse(Scopes.isSingleton(map.get(b)));
+    assertFalse(Scopes.isSingleton(map.get(c)));
+    assertFalse(Scopes.isSingleton(map.get(d)));
+    assertFalse(Scopes.isSingleton(map.get(e)));
+    assertFalse(Scopes.isSingleton(map.get(f)));
+
+    Injector injector = Guice.createInjector(singletonBindings);
+    assertFalse(Scopes.isSingleton(injector.getBinding(a)));
+    assertFalse(Scopes.isSingleton(injector.getBinding(b)));
+    assertFalse(Scopes.isSingleton(injector.getBinding(c)));
+    assertFalse(Scopes.isSingleton(injector.getBinding(d)));
+    assertFalse(Scopes.isSingleton(injector.getBinding(e)));
+    assertFalse(Scopes.isSingleton(injector.getBinding(f)));
+  }
+
+  public void testIsScopedPositive() {
+    final Key<String> a = Key.get(String.class, named("A"));
+    final Key<String> b = Key.get(String.class, named("B"));
+    final Key<String> c = Key.get(String.class, named("C"));
+    final Key<String> d = Key.get(String.class, named("D"));
+    final Key<String> e = Key.get(String.class, named("E"));
+    final Key<Object> f = Key.get(Object.class, named("F"));
+    final Key<String> g = Key.get(String.class, named("G"));
+
+    Module customBindings = new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(CustomScoped.class, CUSTOM_SCOPE);
+        bind(a).to(b);
+        bind(b).to(c);
+        bind(c).toProvider(Providers.of("c")).in(CUSTOM_SCOPE);
+        bind(d).toProvider(Providers.of("d")).in(CustomScoped.class);
+        bind(f).to(AnnotatedCustomScoped.class);
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            bind(g).toProvider(Providers.of("g")).in(CustomScoped.class);
+            expose(g);
+          }
+        });
+      }
+
+      @Provides @Named("E") @CustomScoped String provideE() {
+        return "e";
+      }
+    };
+
+    @SuppressWarnings("unchecked") // we know the module contains only bindings
+    List<Element> moduleBindings = Elements.getElements(customBindings);
+    ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings);
+    assertFalse(isCustomScoped(map.get(a))); // linked bindings are not followed by modules
+    assertFalse(isCustomScoped(map.get(b)));
+    assertTrue(isCustomScoped(map.get(c)));
+    assertTrue(isCustomScoped(map.get(d)));
+    assertTrue(isCustomScoped(map.get(e)));
+    assertFalse(isCustomScoped(map.get(f))); // annotated classes are not followed by modules
+    assertTrue(isCustomScoped(map.get(g)));
+
+    Injector injector = Guice.createInjector(customBindings);
+    assertTrue(isCustomScoped(injector.getBinding(a)));
+    assertTrue(isCustomScoped(injector.getBinding(b)));
+    assertTrue(isCustomScoped(injector.getBinding(c)));
+    assertTrue(isCustomScoped(injector.getBinding(d)));
+    assertTrue(isCustomScoped(injector.getBinding(e)));
+    assertTrue(isCustomScoped(injector.getBinding(f)));
+    assertTrue(isCustomScoped(injector.getBinding(g)));
+  }
+
+  public void testIsScopedNegative() {
+    final Key<String> a = Key.get(String.class, named("A"));
+    final Key<String> b = Key.get(String.class, named("B"));
+    final Key<String> c = Key.get(String.class, named("C"));
+    final Key<String> d = Key.get(String.class, named("D"));
+    final Key<String> e = Key.get(String.class, named("E"));
+    final Key<String> f = Key.get(String.class, named("F"));
+    final Key<String> g = Key.get(String.class, named("G"));
+    final Key<String> h = Key.get(String.class, named("H"));
+
+    Module customBindings = new AbstractModule() {
+      @Override protected void configure() {
+        bind(a).to(b);
+        bind(b).to(c);
+        bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE);
+        bind(d).toProvider(Providers.of("d")).in(Singleton.class);
+        install(new PrivateModule() {
+          @Override
+          protected void configure() {
+            bind(f).toProvider(Providers.of("f")).in(Singleton.class);
+            expose(f);
+          }
+        });
+        bind(g).toInstance("g");
+        bind(h).toProvider(Providers.of("h")).asEagerSingleton();
+      }
+
+      @Provides @Named("E") @Singleton String provideE() {
+        return "e";
+      }
+    };
+
+    @SuppressWarnings("unchecked") // we know the module contains only bindings
+    List<Element> moduleBindings = Elements.getElements(customBindings);
+    ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings);
+    assertFalse(isCustomScoped(map.get(a)));
+    assertFalse(isCustomScoped(map.get(b)));
+    assertFalse(isCustomScoped(map.get(c)));
+    assertFalse(isCustomScoped(map.get(d)));
+    assertFalse(isCustomScoped(map.get(e)));
+    assertFalse(isCustomScoped(map.get(f)));
+    assertFalse(isCustomScoped(map.get(g)));
+    assertFalse(isCustomScoped(map.get(h)));
+
+    Injector injector = Guice.createInjector(customBindings);
+    assertFalse(isCustomScoped(injector.getBinding(a)));
+    assertFalse(isCustomScoped(injector.getBinding(b)));
+    assertFalse(isCustomScoped(injector.getBinding(c)));
+    assertFalse(isCustomScoped(injector.getBinding(d)));
+    assertFalse(isCustomScoped(injector.getBinding(e)));
+    assertFalse(isCustomScoped(injector.getBinding(f)));
+    assertFalse(isCustomScoped(injector.getBinding(g)));
+    assertFalse(isCustomScoped(injector.getBinding(h)));
+  }
+
+  private boolean isCustomScoped(Binding<?> binding) {
+    return Scopes.isScoped(binding, CUSTOM_SCOPE, CustomScoped.class);
+  }
+
+  ImmutableMap<Key<?>, Binding<?>> indexBindings(Iterable<Element> elements) {
+    ImmutableMap.Builder<Key<?>, Binding<?>> builder = ImmutableMap.builder();
+    for (Element element : elements) {
+      if (element instanceof Binding) {
+        Binding<?> binding = (Binding<?>) element;
+        builder.put(binding.getKey(), binding);
+      } else if (element instanceof PrivateElements) {
+        PrivateElements privateElements = (PrivateElements)element;
+        Map<Key<?>, Binding<?>> privateBindings = indexBindings(privateElements.getElements());
+        for(Key<?> exposed : privateElements.getExposedKeys()) {
+          builder.put(exposed, privateBindings.get(exposed));
+        }
+      }
+    }
+    return builder.build();
+  }
+
+  @Singleton
+  static class ThrowingSingleton {
+    static int nextInstanceId;
+    final int instanceId = nextInstanceId++;
+
+    ThrowingSingleton() {
+      if (instanceId == 0) {
+        throw new RuntimeException();
+      }
+    }
+  }
+
+  public void testSingletonConstructorThrows() {
+    Injector injector = Guice.createInjector();
+
+    try {
+      injector.getInstance(ThrowingSingleton.class);
+      fail();
+    } catch (ProvisionException expected) {
+    }
+
+    // this behaviour is unspecified. If we change Guice to re-throw the exception, this test
+    // should be changed
+    injector.getInstance(ThrowingSingleton.class);
+    assertEquals(2, ThrowingSingleton.nextInstanceId);
+  }
+
+  /**
+   * Should only be created by {@link SBarrierProvider}.
+   *
+   * <p>{@code S} stands for synchronization.
+   *
+   * @see SBarrierProvider
+   */
+  static class S {
+
+    private S(int preventInjectionWithoutProvider) {
+    }
+  }
+
+  /**
+   * Provides all the instances of S simultaneously using {@link CyclicBarrier} with {@code
+   * nThreads}. Intended to be used for threads synchronization during injection.
+   */
+  static class SBarrierProvider implements Provider<S> {
+
+    final CyclicBarrier barrier;
+    volatile boolean barrierPassed = false;
+
+    SBarrierProvider(int nThreads) {
+      barrier = new CyclicBarrier(nThreads, new Runnable() {
+        public void run() {
+          // would finish before returning from await() for any thread
+          barrierPassed = true;
+        }
+      });
+    }
+
+    public S get() {
+      try {
+        if (!barrierPassed) {
+          // only if we're triggering barrier for the first time
+          barrier.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        }
+      } catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+      return new S(0);
+    }
+  }
+
+  /**
+   * Tests that different injectors should not affect each other.
+   *
+   * <p>This creates a second thread to work in parallel, to create two instances of
+   * {@link S} as the same time. If the lock if not granular enough (i.e. JVM-wide)
+   * then they would block each other creating a deadlock and await timeout.
+   */
+
+  public void testInjectorsDontDeadlockOnSingletons() throws Exception {
+    final Provider<S> provider = new SBarrierProvider(2);
+    final Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        Thread.currentThread().setName("S.class[1]");
+        bind(S.class).toProvider(provider).in(Scopes.SINGLETON);
+      }
+    });
+    final Injector secondInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        Thread.currentThread().setName("S.class[2]");
+        bind(S.class).toProvider(provider).in(Scopes.SINGLETON);
+      }
+    });
+
+    Future<S> secondThreadResult = Executors.newSingleThreadExecutor().submit(new Callable<S>() {
+      public S call() {
+        return secondInjector.getInstance(S.class);
+      }
+    });
+
+    S firstS = injector.getInstance(S.class);
+    S secondS = secondThreadResult.get();
+
+    assertNotSame(firstS, secondS);
+  }
+
+  @ImplementedBy(GImpl.class)
+  interface G {
+
+  }
+
+  @Singleton
+  static class GImpl implements G {
+
+    final H h;
+
+    /**
+     * Relies on Guice implementation to inject S first and H later, which provides a barrier .
+     */
+    @Inject
+    GImpl(S synchronizationBarrier, H h) {
+      this.h = h;
+    }
+  }
+
+  @ImplementedBy(HImpl.class)
+  interface H {
+
+  }
+
+  @Singleton
+  static class HImpl implements H {
+
+    final G g;
+
+    /**
+     * Relies on Guice implementation to inject S first and G later, which provides a barrier .
+     */
+    @Inject
+    HImpl(S synchronizationBarrier, G g) throws Exception {
+      this.g = g;
+    }
+  }
+
+  /**
+   * Tests that injector can create two singletons with circular dependency in parallel.
+   *
+   * <p>This creates two threads to work in parallel, to create instances of
+   * {@link G} and {@link H}. Creation is synchronized by injection of {@link S},
+   * first thread would block until second would be inside a singleton creation as well.
+   *
+   * <p>Both instances are created by sibling injectors, that share singleton scope.
+   * Verifies that exactly one circular proxy object is created.
+   */
+
+  public void testSiblingInjectorGettingCircularSingletonsOneCircularProxy() throws Exception {
+    final Provider<S> provider = new SBarrierProvider(2);
+    final Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(S.class).toProvider(provider);
+      }
+    });
+
+    Future<G> firstThreadResult = Executors.newSingleThreadExecutor().submit(new Callable<G>() {
+      public G call() {
+        Thread.currentThread().setName("G.class");
+        return injector.createChildInjector().getInstance(G.class);
+      }
+    });
+    Future<H> secondThreadResult = Executors.newSingleThreadExecutor().submit(new Callable<H>() {
+      public H call() {
+        Thread.currentThread().setName("H.class");
+        return injector.createChildInjector().getInstance(H.class);
+      }
+    });
+
+    // using separate threads to avoid potential deadlock on the main thread
+    // waiting twice as much to be sure that both would time out in their respective barriers
+    GImpl g = (GImpl) firstThreadResult.get(DEADLOCK_TIMEOUT_SECONDS * 3, TimeUnit.SECONDS);
+    HImpl h = (HImpl) secondThreadResult.get(DEADLOCK_TIMEOUT_SECONDS * 3, TimeUnit.SECONDS);
+
+    // Check that G and H created are not proxied
+    assertTrue(!Scopes.isCircularProxy(g) && !Scopes.isCircularProxy(h));
+
+    // Check that we have no more than one circular proxy created
+    assertFalse(Scopes.isCircularProxy(g.h) && Scopes.isCircularProxy(h.g));
+
+    // Check that non-proxy variable points to another singleton
+    assertTrue(g.h == h || h.g == g);
+
+    // Check correct proxy initialization as default equals implementation would
+    assertEquals(g.h, h);
+    assertEquals(h.g, g);
+  }
+
+  @Singleton
+  static class I0 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    I0(I1 i) {
+    }
+  }
+
+  @Singleton
+  static class I1 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    I1(S synchronizationBarrier, I2 i) {
+    }
+  }
+
+  @Singleton
+  static class I2 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    I2(J1 j) {
+    }
+  }
+
+  @Singleton
+  static class J0 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    J0(J1 j) {
+    }
+  }
+
+  @Singleton
+  static class J1 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    J1(S synchronizationBarrier, J2 j) {
+    }
+  }
+
+  @Singleton
+  static class J2 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    J2(K1 k) {
+    }
+  }
+
+  @Singleton
+  static class K0 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    K0(K1 k) {
+    }
+  }
+
+  @Singleton
+  static class K1 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    K1(S synchronizationBarrier, K2 k) {
+    }
+  }
+
+  @Singleton
+  static class K2 {
+
+    /**
+     * Relies on Guice implementation to inject S first, which provides a barrier .
+     */
+    @Inject
+    K2(I1 i) {
+    }
+  }
+
+  /**
+   * Check that circular dependencies on non-interfaces are correctly resolved in multi-threaded
+   * case. And that an error message constructed is a good one.
+   *
+   * <p>I0 -> I1 -> I2 -> J1 and J0 -> J1 -> J2 -> K1 and K0 -> K1 -> K2,
+   * where I1, J1 and K1 are created in parallel.
+   *
+   * <p>Creation is synchronized by injection of {@link S}, first thread would block until second
+   * would be inside a singleton creation as well.
+   *
+   * <p>Verifies that provision results in an error, that spans two threads and
+   * has a dependency cycle.
+   */
+
+  public void testUnresolvableSingletonCircularDependencyErrorMessage() throws Exception {
+    final Provider<S> provider = new SBarrierProvider(3);
+    final Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(S.class).toProvider(provider);
+      }
+    });
+
+    Future<I0> firstThreadResult = Executors.newSingleThreadExecutor().submit(new Callable<I0>() {
+      public I0 call() {
+        Thread.currentThread().setName("I0.class");
+        return injector.getInstance(I0.class);
+      }
+    });
+    Future<J0> secondThreadResult = Executors.newSingleThreadExecutor().submit(new Callable<J0>() {
+      public J0 call() {
+        Thread.currentThread().setName("J0.class");
+        return injector.getInstance(J0.class);
+      }
+    });
+    Future<K0> thirdThreadResult = Executors.newSingleThreadExecutor().submit(new Callable<K0>() {
+      public K0 call() {
+        Thread.currentThread().setName("K0.class");
+        return injector.getInstance(K0.class);
+      }
+    });
+
+    // using separate threads to avoid potential deadlock on the main thread
+    // waiting twice as much to be sure that both would time out in their respective barriers
+    Throwable firstException = null;
+    Throwable secondException = null;
+    Throwable thirdException = null;
+    try {
+      firstThreadResult.get(DEADLOCK_TIMEOUT_SECONDS * 3, TimeUnit.SECONDS);
+      fail();
+    } catch (ExecutionException e) {
+      firstException = e.getCause();
+    }
+    try {
+      secondThreadResult.get(DEADLOCK_TIMEOUT_SECONDS * 3, TimeUnit.SECONDS);
+      fail();
+    } catch (ExecutionException e) {
+      secondException = e.getCause();
+    }
+    try {
+      thirdThreadResult.get(DEADLOCK_TIMEOUT_SECONDS * 3, TimeUnit.SECONDS);
+      fail();
+    } catch (ExecutionException e) {
+      thirdException = e.getCause();
+    }
+
+    // verification of error messages generated
+    assertEquals(firstException.getClass(), ProvisionException.class);
+    assertEquals(secondException.getClass(), ProvisionException.class);
+    assertEquals(thirdException.getClass(), ProvisionException.class);
+    List<String> errorMessages = Lists.newArrayList(
+        String.format("%s\n%s\n%s",
+            firstException.getMessage(), secondException.getMessage(), thirdException.getMessage())
+            .split("\\n\\n"));
+    Collections.sort(errorMessages, new Comparator<String>() {
+      @Override
+      public int compare(String s1, String s2) {
+        return s2.length() - s1.length();
+      }
+    });
+    // this is brittle, but turns out that second to longest message spans all threads
+    String errorMessage = errorMessages.get(1);
+    assertContains(errorMessage,
+        "Encountered circular dependency spanning several threads. Tried proxying "
+            + this.getClass().getName());
+    assertFalse("Both I0 and J0 can not be a part of a dependency cycle",
+        errorMessage.contains(I0.class.getName()) && errorMessage.contains(J0.class.getName()));
+    assertFalse("Both J0 and K0 can not be a part of a dependency cycle",
+        errorMessage.contains(J0.class.getName()) && errorMessage.contains(K0.class.getName()));
+    assertFalse("Both K0 and I0 can not be a part of a dependency cycle",
+        errorMessage.contains(K0.class.getName()) && errorMessage.contains(I0.class.getName()));
+
+    List<String> firstErrorLineForThread = new ArrayList<String>();
+    boolean addNextLine = false;
+    for (String errorLine : errorMessage.split("\\n")) {
+      if (errorLine.contains("in thread")) {
+        addNextLine = true;
+        firstErrorLineForThread.add(errorLine);
+      } else if (addNextLine) {
+        addNextLine = false;
+        firstErrorLineForThread.add(errorLine);
+      }
+    }
+    assertEquals("we expect to see [T1, $A, T2, $B, T3, $C, T1, $A]",
+        8, firstErrorLineForThread.size());
+    assertEquals("first four elements should be different",
+        6, new HashSet<String>(firstErrorLineForThread.subList(0, 6)).size());
+    assertEquals(firstErrorLineForThread.get(6), firstErrorLineForThread.get(0));
+    assertEquals(firstErrorLineForThread.get(7), firstErrorLineForThread.get(1));
+    assertFalse("K0 thread could not be blocked by J0",
+        firstErrorLineForThread.get(0).contains("J0")
+            && firstErrorLineForThread.get(2).contains("K0"));
+    assertFalse("J0 thread could not be blocked by I0",
+        firstErrorLineForThread.get(0).contains("I0")
+            && firstErrorLineForThread.get(2).contains("J0"));
+    assertFalse("I0 thread could not be blocked by K0",
+        firstErrorLineForThread.get(0).contains("K0")
+            && firstErrorLineForThread.get(2).contains("I0"));
+  }
+}
diff --git a/core/test/com/google/inject/SerializationTest.java b/core/test/com/google/inject/SerializationTest.java
new file mode 100644
index 0000000..df353f6
--- /dev/null
+++ b/core/test/com/google/inject/SerializationTest.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.inject.Asserts.assertSimilarWhenReserialized;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class SerializationTest extends TestCase {
+
+  public void testAbstractModuleIsSerializable() throws IOException {
+    Asserts.reserialize(new MyAbstractModule());
+  }
+  static class MyAbstractModule extends AbstractModule implements Serializable {
+    protected void configure() {}
+  }
+
+  public void testCreationExceptionIsSerializable() throws IOException {
+    assertSimilarWhenReserialized(createCreationException());
+  }
+
+  private CreationException createCreationException() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(List.class);
+        }
+      });
+      throw new AssertionFailedError();
+    } catch (CreationException e) {
+      return e;
+    }
+  }
+
+  static class A {
+    @Inject B b;
+  }
+
+  static class B {}
+}
diff --git a/core/test/com/google/inject/SuiteUtils.java b/core/test/com/google/inject/SuiteUtils.java
new file mode 100644
index 0000000..cd9eb10
--- /dev/null
+++ b/core/test/com/google/inject/SuiteUtils.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import java.util.Enumeration;
+import java.util.Set;
+
+public class SuiteUtils {
+
+  public static TestSuite removeSuppressedTests(TestSuite suite, Set<String> suppressedTestNames) {
+    TestSuite result = new TestSuite(suite.getName());
+  
+    for(Enumeration e = suite.tests(); e.hasMoreElements(); ) {
+      Test test = (Test) e.nextElement();
+  
+      if (suppressedTestNames.contains(test.toString())) {
+        continue;
+      }
+  
+      if (test instanceof TestSuite) {
+        result.addTest(removeSuppressedTests((TestSuite) test, suppressedTestNames));
+      } else {
+        result.addTest(test);
+      }
+    }
+  
+    return result;
+  }
+
+}
diff --git a/core/test/com/google/inject/SuperclassTest.java b/core/test/com/google/inject/SuperclassTest.java
new file mode 100644
index 0000000..3dda585
--- /dev/null
+++ b/core/test/com/google/inject/SuperclassTest.java
@@ -0,0 +1,56 @@
+/**
+ * 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 com.google.inject;
+
+import junit.framework.TestCase;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class SuperclassTest extends TestCase {
+
+  public void testSuperclassInjection() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class);
+      }
+    });
+
+    Provider<Sub> creator = injector.getProvider(Sub.class);
+    Sub sub = creator.get();
+    sub = creator.get();
+    sub = creator.get();
+    sub = creator.get();
+    sub = creator.get();
+    assertNotNull(sub.field);
+    assertNotNull(sub.fromMethod);
+  }
+
+  static abstract class Super {
+    @Inject Foo field;
+
+    Foo fromMethod;
+    @Inject void setC(Foo foo) {
+      fromMethod = foo;
+    }
+  }
+
+  static class Sub extends Super {
+  }
+
+  static class Foo {}
+}
diff --git a/core/test/com/google/inject/TypeConversionTest.java b/core/test/com/google/inject/TypeConversionTest.java
new file mode 100644
index 0000000..e318477
--- /dev/null
+++ b/core/test/com/google/inject/TypeConversionTest.java
@@ -0,0 +1,495 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.asModuleChain;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.Iterables;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.ConvertedConstantBinding;
+import com.google.inject.spi.TypeConverter;
+import com.google.inject.spi.TypeConverterBinding;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.util.Date;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class TypeConversionTest extends TestCase {
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface NumericValue {}
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface BooleanValue {}
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface EnumValue {}
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface ClassName {}
+
+  public static class Foo {
+    @Inject @BooleanValue Boolean booleanField;
+    @Inject @BooleanValue boolean primitiveBooleanField;
+    @Inject @NumericValue Byte byteField;
+    @Inject @NumericValue byte primitiveByteField;
+    @Inject @NumericValue Short shortField;
+    @Inject @NumericValue short primitiveShortField;
+    @Inject @NumericValue Integer integerField;
+    @Inject @NumericValue int primitiveIntField;
+    @Inject @NumericValue Long longField;
+    @Inject @NumericValue long primitiveLongField;
+    @Inject @NumericValue Float floatField;
+    @Inject @NumericValue float primitiveFloatField;
+    @Inject @NumericValue Double doubleField;
+    @Inject @NumericValue double primitiveDoubleField;
+    @Inject @EnumValue Bar enumField;
+    @Inject @ClassName Class<?> classField;
+  }
+
+  public enum Bar {
+    TEE, BAZ, BOB
+  }
+
+  public void testOneConstantInjection() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindConstant().annotatedWith(NumericValue.class).to("5");
+        bind(Simple.class);
+      }
+    });
+
+    Simple simple = injector.getInstance(Simple.class);
+    assertEquals(5, simple.i);
+  }
+
+  static class Simple {
+    @Inject @NumericValue int i;
+  }
+
+  public void testConstantInjection() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindConstant().annotatedWith(NumericValue.class).to("5");
+        bindConstant().annotatedWith(BooleanValue.class).to("true");
+        bindConstant().annotatedWith(EnumValue.class).to("TEE");
+        bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName());
+      }
+    });
+
+    Foo foo = injector.getInstance(Foo.class);
+
+    checkNumbers(
+      foo.integerField,
+      foo.primitiveIntField,
+      foo.longField,
+      foo.primitiveLongField,
+      foo.byteField,
+      foo.primitiveByteField,
+      foo.shortField,
+      foo.primitiveShortField,
+      foo.floatField,
+      foo.primitiveFloatField,
+      foo.doubleField,
+      foo.primitiveDoubleField
+    );
+
+    assertEquals(Bar.TEE, foo.enumField);
+    assertEquals(Foo.class, foo.classField);
+  }
+
+  public void testConstantInjectionWithExplicitBindingsRequired() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class);
+        bindConstant().annotatedWith(NumericValue.class).to("5");
+        bindConstant().annotatedWith(BooleanValue.class).to("true");
+        bindConstant().annotatedWith(EnumValue.class).to("TEE");
+        bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName());
+      }
+    });
+
+    Foo foo = injector.getInstance(Foo.class);
+
+    checkNumbers(
+      foo.integerField,
+      foo.primitiveIntField,
+      foo.longField,
+      foo.primitiveLongField,
+      foo.byteField,
+      foo.primitiveByteField,
+      foo.shortField,
+      foo.primitiveShortField,
+      foo.floatField,
+      foo.primitiveFloatField,
+      foo.doubleField,
+      foo.primitiveDoubleField
+    );
+
+    assertEquals(Bar.TEE, foo.enumField);
+    assertEquals(Foo.class, foo.classField);
+  }
+
+  void checkNumbers(Number... ns) {
+    for (Number n : ns) {
+      assertEquals(5, n.intValue());
+    }
+  }
+
+  static class OuterErrorModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new InnerErrorModule());
+    }
+  }
+
+  static class InnerErrorModule extends AbstractModule {
+    @Override protected void configure() {
+      bindConstant().annotatedWith(NumericValue.class).to("invalid");
+    }
+  }
+
+  public void testInvalidInteger() throws CreationException {
+    Injector injector = Guice.createInjector(new OuterErrorModule());
+    try {
+      injector.getInstance(InvalidInteger.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "Error converting 'invalid' (bound at " + InnerErrorModule.class.getName()
+              + getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterErrorModule.class, InnerErrorModule.class),
+          "using TypeConverter<Integer> which matches identicalTo(class java.lang.Integer)"
+              + " (bound at [unknown source]).",
+          "Reason: java.lang.RuntimeException: For input string: \"invalid\"");
+    }
+  }
+
+  public static class InvalidInteger {
+    @Inject @NumericValue Integer integerField;
+  }
+
+  public void testInvalidCharacter() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindConstant().annotatedWith(NumericValue.class).to("invalid");
+      }
+    });
+
+    try {
+      injector.getInstance(InvalidCharacter.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), "Error converting 'invalid'");
+      assertContains(expected.getMessage(), "bound at " + getClass().getName());
+      assertContains(expected.getMessage(), "to java.lang.Character");
+    }
+  }
+
+  public static class InvalidCharacter {
+    @Inject @NumericValue char foo;
+  }
+
+  public void testInvalidEnum() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindConstant().annotatedWith(NumericValue.class).to("invalid");
+      }
+    });
+
+    try {
+      injector.getInstance(InvalidEnum.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), "Error converting 'invalid'");
+      assertContains(expected.getMessage(), "bound at " + getClass().getName());
+      assertContains(expected.getMessage(), "to " + Bar.class.getName());
+    }
+  }
+
+  public static class InvalidEnum {
+    @Inject @NumericValue Bar foo;
+  }
+
+  public void testToInstanceIsTreatedLikeConstant() throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("5");
+        bind(LongHolder.class);
+      }
+    });
+
+    assertEquals(5L, (long) injector.getInstance(LongHolder.class).foo);
+  }
+
+  static class LongHolder {
+    @Inject Long foo;
+  }
+
+  public void testCustomTypeConversion() throws CreationException {
+    final Date result = new Date();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)) , mockTypeConverter(result));
+        bindConstant().annotatedWith(NumericValue.class).to("Today");
+        bind(DateHolder.class);
+      }
+    });
+
+    assertSame(result, injector.getInstance(DateHolder.class).date);
+
+    Binding<Date> binding = injector.getBinding(Key.get(Date.class, NumericValue.class));
+    assertTrue(binding instanceof ConvertedConstantBinding<?>);
+
+    TypeConverterBinding converterBinding = ((ConvertedConstantBinding<?>)binding).getTypeConverterBinding();
+    assertEquals("CustomConverter", converterBinding.getTypeConverter().toString());
+
+    assertTrue(injector.getTypeConverterBindings().contains(converterBinding));
+  }
+
+  static class InvalidCustomValueModule extends AbstractModule {
+    @Override protected void configure() {
+      convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), failingTypeConverter());
+      bindConstant().annotatedWith(NumericValue.class).to("invalid");
+      bind(DateHolder.class);
+    }
+  }
+
+  public void testInvalidCustomValue() throws CreationException {
+    Module module = new InvalidCustomValueModule();
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException expected) {
+      Throwable cause = Iterables.getOnlyElement(expected.getErrorMessages()).getCause();
+      assertTrue(cause instanceof UnsupportedOperationException);
+      assertContains(expected.getMessage(),
+          "1) Error converting 'invalid' (bound at ", getClass().getName(),
+          getDeclaringSourcePart(getClass()), "to java.util.Date",
+          "using BrokenConverter which matches only(java.util.Date) ",
+          "(bound at " + getClass().getName(), getDeclaringSourcePart(getClass()),
+          "Reason: java.lang.UnsupportedOperationException: Cannot convert",
+          "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:");
+    }
+  }
+
+  static class OuterModule extends AbstractModule {
+    private final Module converterModule;
+    OuterModule(Module converterModule) {
+      this.converterModule = converterModule;
+    }
+
+    @Override protected void configure() {
+      install(new InnerModule(converterModule));
+    }
+  }
+
+  static class InnerModule extends AbstractModule {
+    private final Module converterModule;
+    InnerModule(Module converterModule) {
+      this.converterModule = converterModule;
+    }
+
+    @Override protected void configure() {
+      install(converterModule);
+      bindConstant().annotatedWith(NumericValue.class).to("foo");
+      bind(DateHolder.class);
+    }
+  }
+
+  class ConverterNullModule extends AbstractModule {
+    @Override protected void configure() {
+      convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(null));
+    }
+  }
+
+  public void testNullCustomValue() {
+    try {
+      Guice.createInjector(new OuterModule(new ConverterNullModule()));
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Received null converting 'foo' (bound at ",
+          getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterModule.class, InnerModule.class),
+          "to java.util.Date",
+          "using CustomConverter which matches only(java.util.Date) ",
+          "(bound at " + getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterModule.class, InnerModule.class, ConverterNullModule.class),
+          "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:",
+          asModuleChain(OuterModule.class, InnerModule.class));
+    }
+  }
+
+  class ConverterCustomModule extends AbstractModule {
+    @Override protected void configure() {
+      convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(-1));
+    }
+  }
+
+  public void testCustomValueTypeMismatch() {
+    try {
+      Guice.createInjector(new OuterModule(new ConverterCustomModule()));
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Type mismatch converting 'foo' (bound at ",
+          getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterModule.class, InnerModule.class),
+          "to java.util.Date",
+          "using CustomConverter which matches only(java.util.Date) ",
+          "(bound at " + getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterModule.class, InnerModule.class, ConverterCustomModule.class),
+          "Converter returned -1.",
+          "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:",
+          asModuleChain(OuterModule.class, InnerModule.class));
+    }
+  }
+
+  public void testStringIsConvertedOnlyOnce() {
+    final TypeConverter converter = new TypeConverter() {
+      boolean converted = false;
+      public Object convert(String value, TypeLiteral<?> toType) {
+        if (converted) {
+          throw new AssertionFailedError("converted multiple times!");
+        }
+        converted = true;
+        return new Date();
+      }
+    };
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), converter);
+        bindConstant().annotatedWith(NumericValue.class).to("unused");
+      }
+    });
+
+    Date first = injector.getInstance(Key.get(Date.class, NumericValue.class));
+    Date second = injector.getInstance(Key.get(Date.class, NumericValue.class));
+    assertSame(first, second);
+  }
+
+  class OuterAmbiguousModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new InnerAmbiguousModule());
+    }
+  }
+
+  class InnerAmbiguousModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new Ambiguous1Module());
+      install(new Ambiguous2Module());
+      bindConstant().annotatedWith(NumericValue.class).to("foo");
+      bind(DateHolder.class);
+    }
+  }
+
+  class Ambiguous1Module extends AbstractModule {
+    @Override protected void configure() {
+      convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(new Date()));
+    }
+  }
+
+  class Ambiguous2Module extends AbstractModule {
+    @Override protected void configure() {
+      convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(new Date()));
+    }
+  }
+
+  public void testAmbiguousTypeConversion() {
+    try {
+      Guice.createInjector(new OuterAmbiguousModule());
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Multiple converters can convert 'foo' (bound at ", getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterAmbiguousModule.class, InnerAmbiguousModule.class),
+          "to java.util.Date:",
+          "CustomConverter which matches only(java.util.Date) (bound at "
+              + Ambiguous1Module.class.getName()
+              + getDeclaringSourcePart(getClass()),
+          asModuleChain(
+              OuterAmbiguousModule.class, InnerAmbiguousModule.class, Ambiguous1Module.class),
+          "and",
+          "CustomConverter which matches only(java.util.Date) (bound at "
+              + Ambiguous2Module.class.getName()
+              + getDeclaringSourcePart(getClass()),
+          asModuleChain(
+              OuterAmbiguousModule.class, InnerAmbiguousModule.class, Ambiguous2Module.class),
+          "Please adjust your type converter configuration to avoid overlapping matches.",
+          "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:");
+    }
+  }
+
+  TypeConverter mockTypeConverter(final Object result) {
+    return new TypeConverter() {
+      public Object convert(String value, TypeLiteral<?> toType) {
+        return result;
+      }
+
+      @Override public String toString() {
+        return "CustomConverter";
+      }
+    };
+  }
+
+  private static TypeConverter failingTypeConverter() {
+    return new TypeConverter() {
+      public Object convert(String value, TypeLiteral<?> toType) {
+        throw new UnsupportedOperationException("Cannot convert");
+      }
+      @Override public String toString() {
+        return "BrokenConverter";
+      }
+    };
+  }
+
+  static class DateHolder {
+    @Inject @NumericValue Date date;
+  }
+
+  public void testCannotConvertUnannotatedBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("55");
+      }
+    });
+
+    try {
+      injector.getInstance(Integer.class);
+      fail("Converted an unannotated String to an Integer");
+    } catch (ConfigurationException expected) {
+      Asserts.assertContains(expected.getMessage(),
+          "Could not find a suitable constructor in java.lang.Integer.");
+    }
+  }
+}
diff --git a/core/test/com/google/inject/TypeListenerTest.java b/core/test/com/google/inject/TypeListenerTest.java
new file mode 100644
index 0000000..ba7520d
--- /dev/null
+++ b/core/test/com/google/inject/TypeListenerTest.java
@@ -0,0 +1,710 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.asModuleChain;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static com.google.inject.matcher.Matchers.any;
+import static com.google.inject.matcher.Matchers.only;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.InjectionListener;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.TypeEncounter;
+import com.google.inject.spi.TypeListener;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class TypeListenerTest extends TestCase {
+
+  private final Matcher<Object> onlyAbcd = Matchers.only(new TypeLiteral<A>() {})
+      .or(only(new TypeLiteral<B>() {}))
+      .or(only(new TypeLiteral<C>() {}))
+      .or(only(new TypeLiteral<D>() {}));
+
+  final TypeListener failingTypeListener = new TypeListener() {
+    int failures = 0;
+
+    public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+      throw new ClassCastException("whoops, failure #" + (++failures));
+    }
+
+    @Override public String toString() {
+      return "clumsy";
+    }
+  };
+
+  final InjectionListener<Object> failingInjectionListener = new InjectionListener<Object>() {
+    int failures = 0;
+
+    public void afterInjection(Object injectee) {
+      throw new ClassCastException("whoops, failure #" + (++failures));
+    }
+
+    @Override public String toString() {
+      return "goofy";
+    }
+  };
+
+  final MembersInjector<Object> failingMembersInjector = new MembersInjector<Object>() {
+    int failures = 0;
+
+    public void injectMembers(Object instance) {
+      throw new ClassCastException("whoops, failure #" + (++failures));
+    }
+
+    @Override public String toString() {
+      return "awkward";
+    }
+  };
+
+  public void testTypeListenersAreFired() {
+    final AtomicInteger firedCount = new AtomicInteger();
+
+    final TypeListener typeListener = new TypeListener() {
+      public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+        assertEquals(new TypeLiteral<A>() {}, type);
+        firedCount.incrementAndGet();
+      }
+    };
+
+    Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(onlyAbcd, typeListener);
+        bind(A.class);
+      }
+    });
+
+    assertEquals(1, firedCount.get());
+  }
+
+  public void testInstallingInjectionListener() {
+    final List<Object> injectees = Lists.newArrayList();
+    final InjectionListener<Object> injectionListener = new InjectionListener<Object>() {
+      public void afterInjection(Object injectee) {
+        injectees.add(injectee);
+      }
+    };
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(onlyAbcd, new TypeListener() {
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            encounter.register(injectionListener);
+          }
+        });
+        bind(A.class);
+      }
+    });
+
+    assertEquals(ImmutableList.of(), injectees);
+
+    Object a1 = injector.getInstance(A.class);
+    assertEquals(ImmutableList.of(a1), injectees);
+
+    Object a2 = injector.getInstance(A.class);
+    assertEquals(ImmutableList.of(a1, a2), injectees);
+
+    Object b1 = injector.getInstance(B.class);
+    assertEquals(ImmutableList.of(a1, a2, b1), injectees);
+
+    Provider<A> aProvider = injector.getProvider(A.class);
+    assertEquals(ImmutableList.of(a1, a2, b1), injectees);
+    A a3 = aProvider.get();
+    A a4 = aProvider.get();
+    assertEquals(ImmutableList.of(a1, a2, b1, a3, a4), injectees);
+  }
+  
+  /*if[AOP]*/
+  private static org.aopalliance.intercept.MethodInterceptor prefixInterceptor(
+      final String prefix) {
+    return new org.aopalliance.intercept.MethodInterceptor() {
+      public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation)
+          throws Throwable {
+        return prefix + methodInvocation.proceed();
+      }
+    };
+  }
+
+  public void testAddingInterceptors() throws NoSuchMethodException {
+    final Matcher<Object> buzz = only(C.class.getMethod("buzz"));
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindInterceptor(any(), buzz, prefixInterceptor("ka"));
+        bindInterceptor(any(), any(), prefixInterceptor("fe"));
+
+        bindListener(onlyAbcd, new TypeListener() {
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            encounter.bindInterceptor(any(), prefixInterceptor("li"));
+            encounter.bindInterceptor(buzz, prefixInterceptor("no"));
+          }
+        });
+      }
+    });
+
+    // interceptors must be invoked in the order they're bound.
+    C c = injector.getInstance(C.class);
+    assertEquals("kafelinobuzz", c.buzz());
+    assertEquals("felibeep", c.beep());
+  }
+  /*end[AOP]*/
+
+  class OuterThrowsModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new InnerThrowsModule());
+    }
+  }
+  class InnerThrowsModule extends AbstractModule {
+    @Override protected void configure() {
+      bindListener(onlyAbcd, failingTypeListener);
+      bind(B.class);
+      bind(C.class);
+    }
+  }
+  public void testTypeListenerThrows() {
+    try {
+      Guice.createInjector(new OuterThrowsModule());
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterThrowsModule.class, InnerThrowsModule.class),
+          "of " + B.class.getName(), 
+          "Reason: java.lang.ClassCastException: whoops, failure #1",
+          "2) Error notifying TypeListener clumsy (bound at " + getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          asModuleChain(OuterThrowsModule.class, InnerThrowsModule.class),
+          "of " + C.class.getName(),
+          "Reason: java.lang.ClassCastException: whoops, failure #2");
+    }
+    
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(onlyAbcd, failingTypeListener);
+      }
+    });
+    try {
+      injector.getProvider(B.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          "of " + B.class.getName(),
+          "Reason: java.lang.ClassCastException: whoops, failure #3");
+    }
+
+    // getting it again should yield the same exception #3
+    try {
+      injector.getInstance(B.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(),
+          getDeclaringSourcePart(getClass()),
+          "of " + B.class.getName(),
+          "Reason: java.lang.ClassCastException: whoops, failure #3");
+    }
+
+    // non-injected types do not participate
+    assertSame(Stage.DEVELOPMENT, injector.getInstance(Stage.class));
+  }
+
+  public void testInjectionListenerThrows() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(onlyAbcd, new TypeListener() {
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            encounter.register(failingInjectionListener);
+          }
+        });
+        bind(B.class);
+      }
+    });
+
+    try {
+      injector.getInstance(A.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(),
+          "1) Error notifying InjectionListener goofy of " + A.class.getName(),
+          " Reason: java.lang.ClassCastException: whoops, failure #1");
+    }
+
+    // second time through should be a new cause (#2)
+    try {
+      injector.getInstance(A.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(),
+          "1) Error notifying InjectionListener goofy of " + A.class.getName(),
+          " Reason: java.lang.ClassCastException: whoops, failure #2");
+    }
+
+    // we should get errors for all types, but only on getInstance()
+    Provider<B> bProvider = injector.getProvider(B.class);
+    try {
+      bProvider.get();
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(),
+          "1) Error notifying InjectionListener goofy of " + B.class.getName(),
+          " Reason: java.lang.ClassCastException: whoops, failure #3");
+    }
+
+    // non-injected types do not participate
+    assertSame(Stage.DEVELOPMENT, injector.getInstance(Stage.class));
+  }
+
+  public void testInjectMembersTypeListenerFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          getMembersInjector(A.class);
+          bindListener(onlyAbcd, failingTypeListener);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Error notifying TypeListener clumsy (bound at ",
+          TypeListenerTest.class.getName(), getDeclaringSourcePart(getClass()),
+          "of " + A.class.getName(),
+          " Reason: java.lang.ClassCastException: whoops, failure #1");
+    }
+  }
+
+  public void testConstructedTypeListenerIsTheSameAsMembersInjectorListener() {
+    final AtomicInteger typeEncounters = new AtomicInteger();
+    final AtomicInteger injections = new AtomicInteger();
+
+    final InjectionListener<A> listener = new InjectionListener<A>() {
+      public void afterInjection(A injectee) {
+        injections.incrementAndGet();
+        assertNotNull(injectee.injector);
+      }
+    };
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(onlyAbcd, new TypeListener() {
+          @SuppressWarnings("unchecked")
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            typeEncounters.incrementAndGet();
+            encounter.register((InjectionListener) listener);
+          }
+        });
+
+        bind(A.class);
+        getMembersInjector(A.class);
+      }
+    });
+
+    // creating the injector shouldn't trigger injections
+    assertEquals(0, injections.getAndSet(0));
+
+    // constructing an A should trigger an injection
+    injector.getInstance(A.class);
+    assertEquals(1, injections.getAndSet(0));
+
+    // injecting an A should trigger an injection
+    injector.injectMembers(new A());
+    assertEquals(1, injections.getAndSet(0));
+
+    // getting a provider shouldn't
+    Provider<A> aProvider = injector.getProvider(A.class);
+    MembersInjector<A> aMembersInjector = injector.getMembersInjector(A.class);
+    assertEquals(0, injections.getAndSet(0));
+
+    // exercise the provider
+    aProvider.get();
+    aProvider.get();
+    assertEquals(2, injections.getAndSet(0));
+
+    // exercise the members injector
+    aMembersInjector.injectMembers(new A());
+    aMembersInjector.injectMembers(new A());
+    assertEquals(2, injections.getAndSet(0));
+
+    // we should only have encountered one type
+    assertEquals(1, typeEncounters.getAndSet(0));
+  }
+
+  public void testLookupsAtInjectorCreateTime() {
+    final AtomicReference<Provider<B>> bProviderReference = new AtomicReference<Provider<B>>();
+    final AtomicReference<MembersInjector<A>> aMembersInjectorReference
+        = new AtomicReference<MembersInjector<A>>();
+
+    final InjectionListener<Object> lookupsTester = new InjectionListener<Object>() {
+      public void afterInjection(Object injectee) {
+        assertNotNull(bProviderReference.get().get());
+
+        A a = new A();
+        aMembersInjectorReference.get().injectMembers(a);
+        assertNotNull(a.injector);
+      }
+    };
+
+    Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(only(TypeLiteral.get(C.class)), new TypeListener() {
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            Provider<B> bProvider = encounter.getProvider(B.class);
+            try {
+              bProvider.get();
+              fail();
+            } catch (IllegalStateException expected) {
+              assertEquals("This Provider cannot be used until the Injector has been created.",
+                  expected.getMessage());
+            }
+            bProviderReference.set(bProvider);
+
+            MembersInjector<A> aMembersInjector = encounter.getMembersInjector(A.class);
+            try {
+              aMembersInjector.injectMembers(new A());
+              fail();
+            } catch (IllegalStateException expected) {
+              assertEquals(
+                  "This MembersInjector cannot be used until the Injector has been created.",
+                  expected.getMessage());
+            }
+            aMembersInjectorReference.set(aMembersInjector);
+
+            encounter.register(lookupsTester);
+          }
+        });
+
+        // this ensures the type listener fires, and also the afterInjection() listener
+        bind(C.class).asEagerSingleton();
+      }
+    });
+
+    lookupsTester.afterInjection(null);
+  }
+
+  public void testLookupsPostCreate() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(only(TypeLiteral.get(C.class)), new TypeListener() {
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            assertNotNull(encounter.getProvider(B.class).get());
+
+            A a = new A();
+            encounter.getMembersInjector(A.class).injectMembers(a);
+            assertNotNull(a.injector);
+          }
+        });
+      }
+    });
+    
+    injector.getInstance(C.class);
+  }
+
+  public void testMembersInjector() {
+    final MembersInjector<D> membersInjector = new MembersInjector<D>() {
+      public void injectMembers(D instance) {
+        instance.userInjected++;
+        assertEquals(instance.guiceInjected, instance.userInjected);
+      }
+    };
+
+    final InjectionListener<D> injectionListener = new InjectionListener<D>() {
+      public void afterInjection(D injectee) {
+        assertTrue(injectee.userInjected > 0);
+        injectee.listenersNotified++;
+        assertEquals(injectee.guiceInjected, injectee.listenersNotified);
+      }
+    };
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(onlyAbcd, new TypeListener() {
+          @SuppressWarnings("unchecked")
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            encounter.register((MembersInjector) membersInjector);
+            encounter.register((InjectionListener) injectionListener);
+          }
+        });
+
+        D boundThreeTimes = new D();
+        bind(D.class).annotatedWith(named("i")).toInstance(boundThreeTimes);
+        bind(D.class).annotatedWith(named("ii")).toInstance(boundThreeTimes);
+        bind(D.class).annotatedWith(named("iii")).toInstance(boundThreeTimes);
+      }
+    });
+
+    D boundThreeTimes = injector.getInstance(Key.get(D.class, named("iii")));
+    boundThreeTimes.assertAllCounts(1);
+
+    D getInstance = injector.getInstance(D.class);
+    getInstance.assertAllCounts(1);
+
+    D memberInjection = new D();
+    injector.injectMembers(memberInjection);
+    memberInjection.assertAllCounts(1);
+
+    injector.injectMembers(memberInjection);
+    injector.injectMembers(memberInjection);
+    memberInjection.assertAllCounts(3);
+
+    injector.getMembersInjector(D.class).injectMembers(memberInjection);
+    memberInjection.assertAllCounts(4);
+  }
+
+  public void testMembersInjectorThrows() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(onlyAbcd, new TypeListener() {
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            encounter.register(failingMembersInjector);
+          }
+        });
+        bind(B.class);
+      }
+    });
+
+    try {
+      injector.getInstance(A.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(),
+          "1) Error injecting " + A.class.getName() + " using awkward.",
+          "Reason: java.lang.ClassCastException: whoops, failure #1");
+    }
+
+    // second time through should be a new cause (#2)
+    try {
+      injector.getInstance(A.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(),
+          "1) Error injecting " + A.class.getName() + " using awkward.",
+          "Reason: java.lang.ClassCastException: whoops, failure #2");
+    }
+
+    // we should get errors for all types, but only on getInstance()
+    Provider<B> bProvider = injector.getProvider(B.class);
+    try {
+      bProvider.get();
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(),
+          "1) Error injecting " + B.class.getName() + " using awkward.",
+          "Reason: java.lang.ClassCastException: whoops, failure #3");
+    }
+
+    // non-injected types do not participate
+    assertSame(Stage.DEVELOPMENT, injector.getInstance(Stage.class));
+  }
+
+  /**
+   * We had a bug where we weren't notifying of types encountered for member injection when those
+   * types had no members to be injected. Constructed types are always injected because they always
+   * have at least one injection point: the class constructor.
+   */
+  public void testTypesWithNoInjectableMembersAreNotified() {
+    final AtomicInteger notificationCount = new AtomicInteger();
+
+    Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(onlyAbcd, new TypeListener() {
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            notificationCount.incrementAndGet();
+          }
+        });
+
+        bind(C.class).toInstance(new C());
+      }
+    });
+
+    assertEquals(1, notificationCount.get());
+  }
+
+  public void testEncounterCannotBeUsedAfterHearReturns() {
+    final AtomicReference<TypeEncounter<?>> encounterReference = new AtomicReference<TypeEncounter<?>>();
+
+    Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindListener(any(), new TypeListener() {
+          public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+            encounterReference.set(encounter);
+          }
+        });
+
+        bind(C.class);
+      }
+    });
+    TypeEncounter<?> encounter = encounterReference.get();
+
+    try {
+      encounter.register(new InjectionListener<Object>() {
+        public void afterInjection(Object injectee) {}
+      });
+      fail();
+    } catch (IllegalStateException expected) {
+    }
+
+    /*if[AOP]*/
+    try {
+      encounter.bindInterceptor(any(), new org.aopalliance.intercept.MethodInterceptor() {
+        public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation)
+            throws Throwable {
+          return methodInvocation.proceed();
+        }
+      });
+      fail();
+    } catch (IllegalStateException expected) {
+    }
+    /*end[AOP]*/
+
+    try {
+      encounter.addError(new Exception());
+      fail();
+    } catch (IllegalStateException expected) {
+    }
+
+    try {
+      encounter.getMembersInjector(A.class);
+      fail();
+    } catch (IllegalStateException expected) {
+    }
+
+    try {
+      encounter.getProvider(B.class);
+      fail();
+    } catch (IllegalStateException expected) {
+    }
+  }
+
+  public void testAddErrors() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          requestInjection(new Object());
+          bindListener(Matchers.any(), new TypeListener() {
+            public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+              encounter.addError("There was an error on %s", type);
+              encounter.addError(new IllegalArgumentException("whoops!"));
+              encounter.addError(new Message("And another problem"));
+              encounter.addError(new IllegalStateException());
+            }
+          });
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) There was an error on java.lang.Object",
+          "2) An exception was caught and reported. Message: whoops!",
+          "3) And another problem",
+          "4) An exception was caught and reported. Message: null",
+          "4 errors");
+    }
+  }
+
+  private static class CountingMembersInjector implements MembersInjector<D> {
+    public void injectMembers(D instance) {
+      ++instance.userInjected;
+    }
+  }
+
+  private static class CountingInjectionListener implements InjectionListener<D> {
+    public void afterInjection(D injectee) {
+      ++injectee.listenersNotified;
+    }
+  }
+
+  private static class DuplicatingTypeListener implements TypeListener {
+    int count = 0;
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+      ++count;
+
+      MembersInjector membersInjector = new CountingMembersInjector();
+      encounter.register(membersInjector);
+      encounter.register(membersInjector);
+
+      InjectionListener injectionListener = new CountingInjectionListener();
+      encounter.register(injectionListener);
+      encounter.register(injectionListener);
+    }
+  }
+
+  public void testDeDuplicateTypeListeners() {
+    final DuplicatingTypeListener typeListener = new DuplicatingTypeListener();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(any(), typeListener);
+        bindListener(only(new TypeLiteral<D>() {}), typeListener);
+      }
+    });
+    D d = injector.getInstance(D.class);
+    d.assertAllCounts(1);
+    assertEquals(1, typeListener.count);
+  }
+
+  // TODO: recursively accessing a lookup should fail
+
+  static class A {
+    @Inject Injector injector;
+    @Inject Stage stage;
+  }
+
+  static class B {}
+
+  public static class C {
+    public String buzz() {
+      return "buzz";
+    }
+
+    public String beep() {
+      return "beep";
+    }
+  }
+
+  static class D {
+    int guiceInjected = 0;
+    int userInjected = 0;
+    int listenersNotified = 0;
+
+    @Inject void guiceInjected() {
+      guiceInjected++;
+    }
+
+    void assertAllCounts(int expected) {
+      assertEquals(expected, guiceInjected);
+      assertEquals(expected, userInjected);
+      assertEquals(expected, listenersNotified);
+    }
+  }
+}
diff --git a/core/test/com/google/inject/TypeLiteralInjectionTest.java b/core/test/com/google/inject/TypeLiteralInjectionTest.java
new file mode 100644
index 0000000..1231a81
--- /dev/null
+++ b/core/test/com/google/inject/TypeLiteralInjectionTest.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.util.Types.listOf;
+
+import com.google.inject.util.Types;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Demonstrates type reification.
+ * 
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class TypeLiteralInjectionTest extends TestCase {
+
+  public void testBindingToRawTypeLiteralIsNotAllowed() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(TypeLiteral.class).toInstance(TypeLiteral.get(String.class));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Binding to core guice framework type is not allowed: TypeLiteral");
+    }
+  }
+
+  public void testBindingToParameterizedTypeLiteralIsNotAllowed() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(new TypeLiteral<TypeLiteral<String>>() {})
+              .toInstance(TypeLiteral.get(String.class));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Binding to core guice framework type is not allowed: TypeLiteral");
+    }
+  }
+
+  public void testInjectTypeLiteralWithRawTypes() {
+    C c = Guice.createInjector().getInstance(C.class);
+    assertEquals(TypeLiteral.get(String.class), c.string);
+    assertEquals(TypeLiteral.get(A.class), c.a);
+
+    try {
+      Guice.createInjector().getInstance(B.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), TypeLiteral.class.getName() + "<java.util.List<T>> "
+          + "cannot be used as a key; It is not fully specified.");
+    }
+  }
+
+  public void testInjectTypeLiteralWithClassTypes() {
+    B<Integer> b = Guice.createInjector().getInstance(new Key<B<Integer>>() {});
+    assertEquals(TypeLiteral.get(String.class), b.string);
+    assertEquals(TypeLiteral.get(Integer.class), b.t);
+    assertEquals(TypeLiteral.get(listOf(Integer.class)), b.listOfT);
+    assertEquals(TypeLiteral.get(listOf(Types.subtypeOf(Integer.class))), b.listOfWildcardT);
+  }
+
+  public void testInjectRawTypeLiteral() {
+    try {
+      Guice.createInjector().getInstance(TypeLiteral.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "Cannot inject a TypeLiteral that has no type parameter");
+    }
+  }
+
+  static class A<T> {
+    @Inject TypeLiteral<String> string;
+    @Inject TypeLiteral<List<T>> listOfT;
+    @Inject TypeLiteral<List<? extends T>> listOfWildcardT;
+  }
+
+  static class B<T> extends A<T> {
+    @Inject TypeLiteral<T> t;
+  }
+
+  static class C<T> {
+    @Inject TypeLiteral<String> string;
+    @Inject TypeLiteral<A> a;
+    T t;
+  }
+}
diff --git a/core/test/com/google/inject/TypeLiteralTest.java b/core/test/com/google/inject/TypeLiteralTest.java
new file mode 100644
index 0000000..de8b5da
--- /dev/null
+++ b/core/test/com/google/inject/TypeLiteralTest.java
@@ -0,0 +1,198 @@
+/**
+ * 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 com.google.inject;
+
+import static com.google.inject.Asserts.assertEqualsBothWays;
+import static com.google.inject.Asserts.assertNotSerializable;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.util.Types;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class TypeLiteralTest extends TestCase {
+
+  public void testWithParameterizedType() {
+    TypeLiteral<List<String>> a = new TypeLiteral<List<String>>() {};
+    TypeLiteral<List<String>> b = new TypeLiteral<List<String>>(
+        Types.listOf(String.class)) {};
+    assertEqualsBothWays(a, b);
+  }
+
+  public void testEquality() {
+    TypeLiteral<List<String>> t1 = new TypeLiteral<List<String>>() {};
+    TypeLiteral<List<String>> t2 = new TypeLiteral<List<String>>() {};
+    TypeLiteral<List<Integer>> t3 = new TypeLiteral<List<Integer>>() {};
+    TypeLiteral<String> t4 = new TypeLiteral<String>() {};
+
+    assertEqualsBothWays(t1, t2);
+
+    assertFalse(t2.equals(t3));
+    assertFalse(t3.equals(t2));
+
+    assertFalse(t2.equals(t4));
+    assertFalse(t4.equals(t2));
+
+    TypeLiteral<String> t5 = TypeLiteral.get(String.class);
+    assertEqualsBothWays(t4, t5);
+  }
+
+  public List<? extends CharSequence> wildcardExtends;
+
+  public void testWithWildcardType() throws NoSuchFieldException, IOException {
+    TypeLiteral<?> a = TypeLiteral.get(getClass().getField("wildcardExtends").getGenericType());
+    TypeLiteral<?> b = TypeLiteral.get(Types.listOf(Types.subtypeOf(CharSequence.class)));
+    TypeLiteral<?> c = new TypeLiteral<List<? extends CharSequence>>() {};
+    assertEqualsBothWays(a, b);
+    assertEqualsBothWays(b, c);
+    assertEquals("java.util.List<? extends java.lang.CharSequence>", a.toString());
+    assertEquals("java.util.List<? extends java.lang.CharSequence>", b.toString());
+    assertEquals("java.util.List<? extends java.lang.CharSequence>", c.toString());
+    assertNotSerializable(a);
+    assertNotSerializable(b);
+    assertNotSerializable(c);
+  }
+
+  public void testMissingTypeParameter() {
+    try {
+      new TypeLiteral() {};
+      fail();
+    } catch (RuntimeException e) { /* expected */ }
+  }
+
+  public void testTypesInvolvingArraysForEquality() {
+    TypeLiteral<String[]> stringArray = new TypeLiteral<String[]>() {};
+    assertEquals(stringArray, new TypeLiteral<String[]>() {});
+
+    TypeLiteral<List<String[]>> listOfStringArray
+        = new TypeLiteral<List<String[]>>() {};
+    assertEquals(listOfStringArray, new TypeLiteral<List<String[]>>() {});
+  }
+
+  public void testEqualityOfGenericArrayAndClassArray() {
+    TypeLiteral<String[]> arrayAsClass = TypeLiteral.get(String[].class);
+    TypeLiteral<String[]> arrayAsType = new TypeLiteral<String[]>() {};
+    assertEquals(arrayAsClass, arrayAsType);
+  }
+
+  public void testEqualityOfMultidimensionalGenericArrayAndClassArray() {
+    TypeLiteral<String[][][]> arrayAsClass = TypeLiteral.get(String[][][].class);
+    TypeLiteral<String[][][]> arrayAsType = new TypeLiteral<String[][][]>() {};
+    assertEquals(arrayAsClass, arrayAsType);
+  }
+
+  public void testTypeLiteralsMustHaveRawTypes() {
+    try {
+      TypeLiteral.get(Types.subtypeOf(Runnable.class));
+      fail();
+    } catch (IllegalArgumentException expected) {
+      Asserts.assertContains(expected.getMessage(), "Expected a Class, ParameterizedType, or "
+          + "GenericArrayType, but <? extends java.lang.Runnable> is of type "
+          + "com.google.inject.internal.MoreTypes$WildcardTypeImpl");
+    }
+  }
+
+  /**
+   * Unlike Key, TypeLiteral retains full type information and differentiates
+   * between {@code int.class} and {@code Integer.class}.
+   */
+  public void testDifferentiationBetweenWrappersAndPrimitives() {
+    Class[] primitives = new Class[] {
+        boolean.class, byte.class, short.class, int.class, long.class,
+        float.class, double.class, char.class, void.class
+    };
+    Class[] wrappers = new Class[] {
+        Boolean.class, Byte.class, Short.class, Integer.class, Long.class,
+        Float.class, Double.class, Character.class, Void.class
+    };
+
+    for (int t = 0; t < primitives.length; t++) {
+      @SuppressWarnings("unchecked")
+      TypeLiteral primitiveTl = TypeLiteral.get(primitives[t]);
+      @SuppressWarnings("unchecked")
+      TypeLiteral wrapperTl = TypeLiteral.get(wrappers[t]);
+
+      assertFalse(primitiveTl.equals(wrapperTl));
+      assertEquals(primitives[t], primitiveTl.getType());
+      assertEquals(wrappers[t], wrapperTl.getType());
+      assertEquals(primitives[t], primitiveTl.getRawType());
+      assertEquals(wrappers[t], wrapperTl.getRawType());
+    }
+  }
+
+  public void testSerialization() throws IOException {
+    assertNotSerializable(new TypeLiteral<List<String>>() {});
+  }
+
+  public void testTypeVariableWithNoBound() {
+    TypeVariable<Class<HasTypeParameters>>[] typeVariables
+        = HasTypeParameters.class.getTypeParameters();
+
+    TypeLiteral<?> aTl = TypeLiteral.get(typeVariables[0]);
+    assertEquals(Object.class, aTl.getRawType());
+    assertEquals("A", aTl.toString());
+    TypeVariable<?> aTv = (TypeVariable) aTl.getType();
+    assertEquals(HasTypeParameters.class, aTv.getGenericDeclaration());
+    assertEquals("A", aTv.getName());
+    assertEquals(ImmutableList.<Type>of(Object.class), ImmutableList.copyOf(aTv.getBounds()));
+    assertEquals("A", aTv.toString());
+    assertEqualsBothWays(aTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[0]));
+  }
+
+  public void testTypeVariablesWithSingleBound() {
+    TypeVariable<Class<HasTypeParameters>>[] typeVariables
+        = HasTypeParameters.class.getTypeParameters();
+
+    TypeLiteral<?> cTl = TypeLiteral.get(typeVariables[2]);
+    assertEquals(Object.class, cTl.getRawType());
+    assertEquals("C", cTl.toString());
+    TypeVariable<?> cTv = (TypeVariable) cTl.getType();
+    assertEquals(HasTypeParameters.class, cTv.getGenericDeclaration());
+    assertEquals("C", cTv.getName());
+    assertEquals(ImmutableList.<Type>of(Runnable.class), ImmutableList.copyOf(cTv.getBounds()));
+    assertEquals("C", cTv.toString());
+    assertEqualsBothWays(cTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[2]));
+  }
+
+  public void testTypeVariableWithMultipleBounds() {
+    TypeVariable<Class<HasTypeParameters>>[] typeVariables
+        = HasTypeParameters.class.getTypeParameters();
+
+    TypeLiteral<?> bTl = TypeLiteral.get(typeVariables[1]);
+    assertEquals(Object.class, bTl.getRawType());
+    assertEquals("B", bTl.toString());
+    TypeVariable<?> bTv = (TypeVariable) bTl.getType();
+    assertEquals(HasTypeParameters.class, bTv.getGenericDeclaration());
+    assertEquals("B", bTv.getName());
+    assertEquals(ImmutableList.<Type>of(Types.listOf(typeVariables[0]), Runnable.class),
+        ImmutableList.copyOf(bTv.getBounds()));
+    assertEquals("B", bTv.toString());
+    assertEqualsBothWays(bTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[1]));
+  }
+
+  class HasTypeParameters<A, B extends List<A> & Runnable, C extends Runnable> {
+    A a; B b; C c;
+  }
+}
diff --git a/core/test/com/google/inject/TypeLiteralTypeResolutionTest.java b/core/test/com/google/inject/TypeLiteralTypeResolutionTest.java
new file mode 100644
index 0000000..64bc4c7
--- /dev/null
+++ b/core/test/com/google/inject/TypeLiteralTypeResolutionTest.java
@@ -0,0 +1,331 @@
+/**
+ * Copyright (C) 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.inject;
+
+import static com.google.inject.Asserts.assertEqualsBothWays;
+import static com.google.inject.Asserts.assertNotSerializable;
+import static com.google.inject.util.Types.arrayOf;
+import static com.google.inject.util.Types.listOf;
+import static com.google.inject.util.Types.newParameterizedType;
+import static com.google.inject.util.Types.newParameterizedTypeWithOwner;
+import static com.google.inject.util.Types.setOf;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.util.Types;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.AbstractCollection;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This test checks that TypeLiteral can perform type resolution on its members.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class TypeLiteralTypeResolutionTest extends TestCase {
+  Type arrayListOfString = newParameterizedType(ArrayList.class, String.class);
+  Type hasGenericFieldsOfShort = newParameterizedTypeWithOwner(
+      getClass(), HasGenericFields.class, Short.class);
+  Type hasGenericConstructorOfShort = newParameterizedTypeWithOwner(
+      getClass(), GenericConstructor.class, Short.class);
+  Type throwerOfNpe = newParameterizedTypeWithOwner(
+      getClass(), Thrower.class, NullPointerException.class);
+  Type hasArrayOfShort = newParameterizedTypeWithOwner(getClass(), HasArray.class, Short.class);
+  Type hasRelatedOfString = newParameterizedTypeWithOwner(
+      getClass(), HasRelated.class, String.class, String.class);
+  Type mapK = Map.class.getTypeParameters()[0];
+  Type hashMapK = HashMap.class.getTypeParameters()[0];
+  Type setEntryKV;
+  Type entryStringInteger = setOf(newParameterizedTypeWithOwner(
+      Map.class, Map.Entry.class, String.class, Integer.class));
+  Field list;
+  Field instance;
+  Constructor<GenericConstructor> newHasGenericConstructor;
+  Constructor<Thrower> newThrower;
+  Constructor newString;
+  Method stringIndexOf;
+  Method comparableCompareTo;
+  Method getArray;
+  Method getSetOfArray;
+  Method echo;
+  Method throwS;
+
+  @Override protected void setUp() throws Exception {
+    super.setUp();
+
+    list = HasGenericFields.class.getField("list");
+    instance = HasGenericFields.class.getField("instance");
+    newHasGenericConstructor = GenericConstructor.class.getConstructor(Object.class, Object.class);
+    newThrower = Thrower.class.getConstructor();
+    stringIndexOf = String.class.getMethod("indexOf", String.class);
+    newString = String.class.getConstructor(String.class);
+    comparableCompareTo = Comparable.class.getMethod("compareTo", Object.class);
+    getArray = HasArray.class.getMethod("getArray");
+    getSetOfArray = HasArray.class.getMethod("getSetOfArray");
+    echo = HasRelated.class.getMethod("echo", Object.class);
+    throwS = Thrower.class.getMethod("throwS");
+    setEntryKV = HashMap.class.getMethod("entrySet").getGenericReturnType();
+  }
+
+  public void testDirectInheritance() throws NoSuchMethodException {
+    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
+    assertEquals(listOf(String.class),
+        resolver.getReturnType(List.class.getMethod("subList", int.class, int.class)).getType());
+    assertEquals(ImmutableList.<TypeLiteral<?>>of(TypeLiteral.get(String.class)),
+        resolver.getParameterTypes(Collection.class.getMethod("add", Object.class)));
+  }
+  
+  public void testGenericSupertype() {
+    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
+    assertEquals(newParameterizedType(Collection.class, String.class),
+        resolver.getSupertype(Collection.class).getType());
+    assertEquals(newParameterizedType(Iterable.class, String.class),
+        resolver.getSupertype(Iterable.class).getType());
+    assertEquals(newParameterizedType(AbstractList.class, String.class),
+        resolver.getSupertype(AbstractList.class).getType());
+    assertEquals(Object.class, resolver.getSupertype(Object.class).getType());
+  }
+
+  public void testRecursiveTypeVariable() {
+    TypeLiteral<?> resolver = TypeLiteral.get(MyInteger.class);
+    assertEquals(MyInteger.class, resolver.getParameterTypes(comparableCompareTo).get(0).getType());
+  }
+
+  interface MyComparable<E extends MyComparable<E>> extends Comparable<E> {}
+
+  static class MyInteger implements MyComparable<MyInteger> {
+    int value;
+    public int compareTo(MyInteger o) {
+      return value - o.value;
+    }
+  }
+  
+  public void testFields() {
+    TypeLiteral<?> resolver = TypeLiteral.get(hasGenericFieldsOfShort);
+    assertEquals(listOf(Short.class), resolver.getFieldType(list).getType());
+    assertEquals(Short.class, resolver.getFieldType(instance).getType());
+  }
+
+  static class HasGenericFields<T> {
+    public List<T> list;
+    public T instance;
+  }
+
+  public void testGenericConstructor() throws NoSuchMethodException {
+    TypeLiteral<?> resolver = TypeLiteral.get(hasGenericConstructorOfShort);
+    assertEquals(Short.class,
+        resolver.getParameterTypes(newHasGenericConstructor).get(0).getType());
+  }
+
+  static class GenericConstructor<S> {
+    @SuppressWarnings("UnusedDeclaration")
+    public <T> GenericConstructor(S s, T t) {}
+  }
+
+  public void testThrowsExceptions() {
+    TypeLiteral<?> type = TypeLiteral.get(throwerOfNpe);
+    assertEquals(NullPointerException.class, type.getExceptionTypes(newThrower).get(0).getType());
+    assertEquals(NullPointerException.class, type.getExceptionTypes(throwS).get(0).getType());
+  }
+
+  static class Thrower<S extends Exception> {
+    public Thrower() throws S {}
+    public void throwS() throws S {}
+  }
+
+  public void testArrays() {
+    TypeLiteral<?> resolver = TypeLiteral.get(hasArrayOfShort);
+    assertEquals(arrayOf(Short.class), resolver.getReturnType(getArray).getType());
+    assertEquals(setOf(arrayOf(Short.class)), resolver.getReturnType(getSetOfArray).getType());
+  }
+
+  static interface HasArray<T extends Number> {
+    T[] getArray();
+    Set<T[]> getSetOfArray();
+  }
+
+  public void testRelatedTypeVariables() {
+    TypeLiteral<?> resolver = TypeLiteral.get(hasRelatedOfString);
+    assertEquals(String.class, resolver.getParameterTypes(echo).get(0).getType());
+    assertEquals(String.class, resolver.getReturnType(echo).getType());
+  }
+
+  interface HasRelated<T, R extends T> {
+    T echo(R r);
+  }
+
+  /** Ensure the cache doesn't cache too much */
+  public void testCachingAndReindexing() throws NoSuchMethodException {
+    TypeLiteral<?> resolver = TypeLiteral.get(
+        newParameterizedTypeWithOwner(getClass(), HasLists.class, String.class, Short.class));
+    assertEquals(listOf(String.class),
+        resolver.getReturnType(HasLists.class.getMethod("listS")).getType());
+    assertEquals(listOf(Short.class),
+        resolver.getReturnType(HasLists.class.getMethod("listT")).getType());
+  }
+
+  interface HasLists<S, T> {
+    List<S> listS();
+    List<T> listT();
+    List<Map.Entry<S, T>> listEntries();
+  }
+
+  public void testUnsupportedQueries() throws NoSuchMethodException {
+    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
+
+    try {
+      resolver.getExceptionTypes(stringIndexOf);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
+          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
+    }
+    try {
+      resolver.getParameterTypes(stringIndexOf);
+      fail();
+    } catch (Exception e) {
+      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
+          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
+    }
+    try {
+      resolver.getReturnType(stringIndexOf);
+      fail();
+    } catch (Exception e) {
+      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
+          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
+    }
+    try {
+      resolver.getSupertype(String.class);
+      fail();
+    } catch (Exception e) {
+      assertEquals("class java.lang.String is not a supertype of "
+          + "java.util.ArrayList<java.lang.String>", e.getMessage());
+    }
+    try {
+      resolver.getExceptionTypes(newString);
+      fail();
+    } catch (Exception e) {
+      assertEquals("public java.lang.String(java.lang.String) does not construct "
+          + "a supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
+    }
+    try {
+      resolver.getParameterTypes(newString);
+      fail();
+    } catch (Exception e) {
+      assertEquals("public java.lang.String(java.lang.String) does not construct "
+          + "a supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
+    }
+  }
+
+  public void testResolve() {
+    TypeLiteral<?> typeResolver = TypeLiteral.get(StringIntegerMap.class);
+    assertEquals(String.class, typeResolver.resolveType(mapK));
+
+    typeResolver = new TypeLiteral<Map<String, Integer>>() {};
+    assertEquals(String.class, typeResolver.resolveType(mapK));
+    assertEquals(Types.mapOf(String.class, Integer.class),
+        typeResolver.getSupertype(Map.class).getType());
+
+    typeResolver = new TypeLiteral<BetterMap<String, Integer>>() {};
+    assertEquals(String.class, typeResolver.resolveType(mapK));
+
+    typeResolver = new TypeLiteral<BestMap<String, Integer>>() {};
+    assertEquals(String.class, typeResolver.resolveType(mapK));
+
+    typeResolver = TypeLiteral.get(StringIntegerHashMap.class);
+    assertEquals(String.class, typeResolver.resolveType(mapK));
+    assertEquals(String.class, typeResolver.resolveType(hashMapK));
+    assertEquals(entryStringInteger, typeResolver.resolveType(setEntryKV));
+    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
+  }
+
+  public void testOnObject() {
+    TypeLiteral<?> typeResolver = TypeLiteral.get(Object.class);
+    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
+    assertEquals(Object.class, typeResolver.getRawType());
+
+    // interfaces also resolve Object
+    typeResolver = TypeLiteral.get(Types.setOf(Integer.class));
+    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
+  }
+
+  interface StringIntegerMap extends Map<String, Integer> {}
+  interface BetterMap<K1, V1> extends Map<K1, V1> {}
+  interface BestMap<K2, V2> extends BetterMap<K2, V2> {}
+  static class StringIntegerHashMap extends HashMap<String, Integer> {}
+
+  public void testGetSupertype() {
+    TypeLiteral<AbstractList<String>> listOfString = new TypeLiteral<AbstractList<String>>() {};
+    assertEquals(Types.newParameterizedType(AbstractCollection.class, String.class),
+        listOfString.getSupertype(AbstractCollection.class).getType());
+
+    TypeLiteral arrayListOfE = TypeLiteral.get(newParameterizedType(
+        ArrayList.class, ArrayList.class.getTypeParameters()));
+    assertEquals(
+        newParameterizedType(AbstractCollection.class, ArrayList.class.getTypeParameters()),
+        arrayListOfE.getSupertype(AbstractCollection.class).getType());
+  }
+
+  public void testGetSupertypeForArraysAsList() {
+    Class<? extends List> arraysAsListClass = Arrays.asList().getClass();
+    Type anotherE = arraysAsListClass.getTypeParameters()[0];
+    TypeLiteral type = TypeLiteral.get(newParameterizedType(AbstractList.class, anotherE));
+    assertEquals(newParameterizedType(AbstractCollection.class, anotherE),
+        type.getSupertype(AbstractCollection.class).getType());
+  }
+
+  public void testWildcards() throws NoSuchFieldException {
+    TypeLiteral<Parameterized<String>> ofString = new TypeLiteral<Parameterized<String>>() {};
+
+    assertEquals(new TypeLiteral<List<String>>() {}.getType(),
+        ofString.getFieldType(Parameterized.class.getField("t")).getType());
+    assertEquals(new TypeLiteral<List<? extends String>>() {}.getType(),
+        ofString.getFieldType(Parameterized.class.getField("extendsT")).getType());
+    assertEquals(new TypeLiteral<List<? super String>>() {}.getType(),
+        ofString.getFieldType(Parameterized.class.getField("superT")).getType());
+  }
+
+  static class Parameterized<T> {
+    public List<T> t;
+    public List<? extends T> extendsT;
+    public List<? super T> superT;
+  }
+
+  // TODO(jessewilson): tests for tricky bounded types like <T extends Collection, Serializable>
+
+  public void testEqualsAndHashCode() throws IOException {
+    TypeLiteral<?> a1 = TypeLiteral.get(arrayListOfString);
+    TypeLiteral<?> a2 = TypeLiteral.get(arrayListOfString);
+    TypeLiteral<?> b = TypeLiteral.get(listOf(String.class));
+    assertEqualsBothWays(a1, a2);
+    assertNotSerializable(a1);
+    assertFalse(a1.equals(b));
+  }
+}
diff --git a/core/test/com/google/inject/example/ClientServiceWithDependencyInjection.java b/core/test/com/google/inject/example/ClientServiceWithDependencyInjection.java
new file mode 100644
index 0000000..838a60b
--- /dev/null
+++ b/core/test/com/google/inject/example/ClientServiceWithDependencyInjection.java
@@ -0,0 +1,95 @@
+/**
+ * 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 com.google.inject.example;
+
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ClientServiceWithDependencyInjection {
+
+// 62 lines
+
+public interface Service {
+  void go();
+}
+
+public static class ServiceImpl implements ClientServiceWithDependencyInjection.Service {
+  public void go() {
+    // ...
+  }
+}
+
+public static class ServiceFactory {
+
+  private ServiceFactory() {}
+
+  private static final Service service = new ServiceImpl();
+
+  public static Service getInstance() {
+    return service;
+  }
+}
+
+public static class Client {
+
+  private final Service service;
+
+  public Client(Service service) {
+    this.service = service;
+  }
+
+  public void go() {
+    service.go();
+  }
+}
+
+public static class ClientFactory {
+
+  private ClientFactory() {}
+
+  public static Client getInstance() {
+    Service service = ServiceFactory.getInstance();
+    return new Client(service);
+  }
+}
+
+public void testClient() {
+  MockService mock = new MockService();
+  Client client = new Client(mock);
+  client.go();
+  assertTrue(mock.isGone());
+}
+
+public static class MockService implements Service {
+
+  private boolean gone = false;
+
+  public void go() {
+    gone = true;
+  }
+
+  public boolean isGone() {
+    return gone;
+  }
+}
+
+  public static void main(String[] args) {
+    new ClientServiceWithDependencyInjection().testClient();
+  }
+}
diff --git a/core/test/com/google/inject/example/ClientServiceWithFactories.java b/core/test/com/google/inject/example/ClientServiceWithFactories.java
new file mode 100644
index 0000000..b3829a1
--- /dev/null
+++ b/core/test/com/google/inject/example/ClientServiceWithFactories.java
@@ -0,0 +1,91 @@
+/**
+ * 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 com.google.inject.example;
+
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ClientServiceWithFactories {
+
+// 58 lines
+
+public interface Service {
+  void go();
+}
+
+public static class ServiceImpl implements Service {
+  public void go() {
+    // ...
+  }
+}
+
+public static class ServiceFactory {
+
+  private ServiceFactory() {}
+
+  private static Service instance = new ServiceImpl();
+
+  public static Service getInstance() {
+    return instance;
+  }
+
+  public static void setInstance(Service service) {
+    instance = service;
+  }
+}
+
+public static class Client {
+
+  public void go() {
+    Service service = ServiceFactory.getInstance();
+    service.go();
+  }
+}
+
+public void testClient() {
+  Service previous = ServiceFactory.getInstance();
+  try {
+    final MockService mock = new MockService();
+    ServiceFactory.setInstance(mock);
+    Client client = new Client();
+    client.go();
+    assertTrue(mock.isGone());
+  }
+  finally {
+    ServiceFactory.setInstance(previous);
+  }
+}
+
+public static class MockService implements Service {
+
+  private boolean gone = false;
+
+  public void go() {
+    gone = true;
+  }
+
+  public boolean isGone() {
+    return gone;
+  }
+}
+
+  public static void main(String[] args) {
+    new ClientServiceWithFactories().testClient();
+  }
+}
diff --git a/core/test/com/google/inject/example/ClientServiceWithGuice.java b/core/test/com/google/inject/example/ClientServiceWithGuice.java
new file mode 100644
index 0000000..c027377
--- /dev/null
+++ b/core/test/com/google/inject/example/ClientServiceWithGuice.java
@@ -0,0 +1,90 @@
+/**
+ * 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 com.google.inject.example;
+
+import static junit.framework.Assert.assertTrue;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Scopes;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ClientServiceWithGuice {
+
+// 48 lines
+
+public interface Service {
+  void go();
+}
+
+public static class ServiceImpl implements Service {
+  public void go() {
+    // ...
+  }
+}
+
+public static class MyModule extends AbstractModule {
+  protected void configure() {
+    bind(Service.class).to(ServiceImpl.class).in(Scopes.SINGLETON);
+  }
+}
+
+public static class Client {
+
+  private final Service service;
+
+  @Inject
+  public Client(Service service) {
+    this.service = service;
+  }
+
+  public void go() {
+    service.go();
+  }
+}
+
+public void testClient() {
+  MockService mock = new MockService();
+  Client client = new Client(mock);
+  client.go();
+  assertTrue(mock.isGone());
+}
+
+public static class MockService implements Service {
+
+  private boolean gone = false;
+
+  public void go() {
+    gone = true;
+  }
+
+  public boolean isGone() {
+    return gone;
+  }
+}
+
+public static void main(String[] args) throws CreationException {
+  new ClientServiceWithGuice().testClient();
+  Injector injector = Guice.createInjector(new MyModule());
+  Client client = injector.getInstance(Client.class);
+}
+}
diff --git a/core/test/com/google/inject/example/ClientServiceWithGuiceDefaults.java b/core/test/com/google/inject/example/ClientServiceWithGuiceDefaults.java
new file mode 100644
index 0000000..5a3d9a7
--- /dev/null
+++ b/core/test/com/google/inject/example/ClientServiceWithGuiceDefaults.java
@@ -0,0 +1,86 @@
+/**
+ * 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 com.google.inject.example;
+
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.ImplementedBy;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+
+import junit.framework.Assert;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ClientServiceWithGuiceDefaults {
+
+// 44 lines
+
+@ImplementedBy(ServiceImpl.class)
+public interface Service {
+  void go();
+}
+
+@Singleton
+public static class ServiceImpl implements ClientServiceWithGuiceDefaults.Service {
+  public void go() {
+    // ...
+  }
+}
+
+public static class Client {
+
+  private final Service service;
+
+  @Inject
+  public Client(Service service) {
+    this.service = service;
+  }
+
+  public void go() {
+    service.go();
+  }
+}
+
+public void testClient() {
+  MockService mock = new MockService();
+  Client client = new Client(mock);
+  client.go();
+  Assert.assertTrue(mock.isGone());
+}
+
+public static class MockService implements Service {
+
+  private boolean gone = false;
+
+  public void go() {
+    gone = true;
+  }
+
+  public boolean isGone() {
+    return gone;
+  }
+}
+
+public static void main(String[] args) throws CreationException {
+  new ClientServiceWithGuiceDefaults().testClient();
+  Injector injector = Guice.createInjector();
+  Client client = injector.getProvider(Client.class).get();
+}
+}
diff --git a/core/test/com/google/inject/example/JndiProvider.java b/core/test/com/google/inject/example/JndiProvider.java
new file mode 100644
index 0000000..fd90dc0
--- /dev/null
+++ b/core/test/com/google/inject/example/JndiProvider.java
@@ -0,0 +1,53 @@
+/**
+ * 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 com.google.inject.example;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+class JndiProvider<T> implements Provider<T> {
+
+  @Inject Context context;
+  final String name;
+  final Class<T> type;
+
+  JndiProvider(Class<T> type, String name) {
+    this.name = name;
+    this.type = type;
+  }
+
+  public T get() {
+    try {
+      return type.cast(context.lookup(name));
+    }
+    catch (NamingException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Creates a JNDI provider for the given
+   * type and name.
+   */
+  static <T> Provider<T> fromJndi(
+      Class<T> type, String name) {
+    return new JndiProvider<T>(type, name);
+  }
+}
diff --git a/core/test/com/google/inject/example/JndiProviderClient.java b/core/test/com/google/inject/example/JndiProviderClient.java
new file mode 100644
index 0000000..897b249
--- /dev/null
+++ b/core/test/com/google/inject/example/JndiProviderClient.java
@@ -0,0 +1,44 @@
+/**
+ * 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 com.google.inject.example;
+
+import static com.google.inject.example.JndiProvider.fromJndi;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.sql.DataSource;
+
+class JndiProviderClient {
+
+  public static void main(String[] args) throws CreationException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+// Bind Context to the default InitialContext.
+bind(Context.class).to(InitialContext.class);
+
+// Bind to DataSource from JNDI.
+bind(DataSource.class)
+    .toProvider(fromJndi(DataSource.class, "..."));
+      }
+    });
+  }
+}
diff --git a/core/test/com/google/inject/internal/CycleDetectingLockTest.java b/core/test/com/google/inject/internal/CycleDetectingLockTest.java
new file mode 100644
index 0000000..0d10824
--- /dev/null
+++ b/core/test/com/google/inject/internal/CycleDetectingLockTest.java
@@ -0,0 +1,101 @@
+package com.google.inject.internal;
+
+import com.google.inject.internal.CycleDetectingLock.CycleDetectingLockFactory;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class CycleDetectingLockTest extends TestCase {
+
+  static final long DEADLOCK_TIMEOUT_SECONDS = 1;
+
+  /**
+   * Verifies that graph of threads' dependencies is not static and is calculated in runtime using
+   * information about specific locks.
+   *
+   * <pre>
+   *   T1: Waits on S1
+   *   T2: Locks B, sends S1, waits on S2
+   *   T1: Locks A, start locking B, sends S2, waits on S3
+   *   T2: Unlocks B, start locking A, sends S3, finishes locking A, unlocks A
+   *   T1: Finishes locking B, unlocks B, unlocks A
+   * </pre>
+   *
+   * <p>This should succeed, even though T1 was locked on T2 and T2 is locked on T1 when T2 locks
+   * A. Incorrect implementation detects a cycle waiting on S3.
+   */
+
+  public void testSingletonThreadsRuntimeCircularDependency() throws Exception {
+    final CyclicBarrier signal1 = new CyclicBarrier(2);
+    final CyclicBarrier signal2 = new CyclicBarrier(2);
+    final CyclicBarrier signal3 = new CyclicBarrier(2);
+    CycleDetectingLockFactory<String> lockFactory = new CycleDetectingLockFactory<String>();
+    final CycleDetectingLock<String> lockA =
+        lockFactory.new ReentrantCycleDetectingLock("A", new ReentrantLock() {
+          @Override
+          public void lock() {
+            if (Thread.currentThread().getName().equals("T2")) {
+              try {
+                signal3.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+              } catch (Exception e) {
+                throw new RuntimeException(e);
+              }
+            } else {
+              assertEquals("T1", Thread.currentThread().getName());
+            }
+            super.lock();
+          }
+        });
+    final CycleDetectingLock<String> lockB =
+        lockFactory.new ReentrantCycleDetectingLock("B", new ReentrantLock() {
+          @Override
+          public void lock() {
+            if (Thread.currentThread().getName().equals("T1")) {
+              try {
+                signal2.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+                signal3.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+              } catch (Exception e) {
+                throw new RuntimeException(e);
+              }
+            } else {
+              assertEquals("T2", Thread.currentThread().getName());
+            }
+            super.lock();
+          }
+        });
+    Future<Void> firstThreadResult = Executors.newSingleThreadExecutor().submit(
+        new Callable<Void>() {
+          public Void call() throws Exception {
+            Thread.currentThread().setName("T1");
+            signal1.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+            assertTrue(lockA.lockOrDetectPotentialLocksCycle().isEmpty());
+            assertTrue(lockB.lockOrDetectPotentialLocksCycle().isEmpty());
+            lockB.unlock();
+            lockA.unlock();
+            return null;
+          }
+        });
+    Future<Void> secondThreadResult = Executors.newSingleThreadExecutor().submit(
+        new Callable<Void>() {
+          public Void call() throws Exception {
+            Thread.currentThread().setName("T2");
+            assertTrue(lockB.lockOrDetectPotentialLocksCycle().isEmpty());
+            signal1.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+            signal2.await(DEADLOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+            lockB.unlock();
+            assertTrue(lockA.lockOrDetectPotentialLocksCycle().isEmpty());
+            lockA.unlock();
+            return null;
+          }
+        });
+
+    firstThreadResult.get();
+    secondThreadResult.get();
+  }
+}
diff --git a/core/test/com/google/inject/internal/MoreTypesTest.java b/core/test/com/google/inject/internal/MoreTypesTest.java
new file mode 100644
index 0000000..0ce5504
--- /dev/null
+++ b/core/test/com/google/inject/internal/MoreTypesTest.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2010 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.inject.internal;
+
+import com.google.inject.TypeLiteral;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author schmitt@google.com (Peter Schmitt)
+ */
+public class MoreTypesTest extends TestCase {
+
+  public void testParameterizedTypeToString() {
+    TypeLiteral<Inner<String>> innerString = new TypeLiteral<Inner<String>>(){};
+    assertEquals("com.google.inject.internal.MoreTypesTest$Inner<java.lang.String>",
+        MoreTypes.typeToString(innerString.getType()));
+
+    TypeLiteral<Set<Inner<Integer>>> mapInnerInteger = new TypeLiteral<Set<Inner<Integer>>>() {};
+    assertEquals("java.util.Set<com.google.inject.internal.MoreTypesTest$Inner<java.lang.Integer>>",
+        MoreTypes.typeToString(mapInnerInteger.getType()));
+
+    TypeLiteral<Map<Inner<Long>, Set<Inner<Long>>>> mapInnerLongToSetInnerLong =
+        new TypeLiteral<Map<Inner<Long>, Set<Inner<Long>>>>() {};
+    assertEquals("java.util.Map<com.google.inject.internal.MoreTypesTest$Inner<java.lang.Long>, "
+            + "java.util.Set<com.google.inject.internal.MoreTypesTest$Inner<java.lang.Long>>>",
+        MoreTypes.typeToString(mapInnerLongToSetInnerLong.getType()));
+  }
+
+  public <T> void testEquals_typeVariable() throws Exception {
+    Type type = getClass().getMethod("testEquals_typeVariable").getTypeParameters()[0];
+    assertTrue(MoreTypes.equals(new TypeLiteral<T>() {}.getType(), type));
+  }
+
+  public static class Inner<T> {}
+}
diff --git a/core/test/com/google/inject/internal/ProxyFactoryTest.java b/core/test/com/google/inject/internal/ProxyFactoryTest.java
new file mode 100644
index 0000000..ce8caa6
--- /dev/null
+++ b/core/test/com/google/inject/internal/ProxyFactoryTest.java
@@ -0,0 +1,209 @@
+/**
+ * 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 com.google.inject.internal;
+
+import static com.google.inject.matcher.Matchers.annotatedWith;
+import static com.google.inject.matcher.Matchers.any;
+import static com.google.inject.matcher.Matchers.not;
+import static com.google.inject.matcher.Matchers.only;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import com.google.inject.spi.InjectionPoint;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ProxyFactoryTest extends TestCase {
+
+  List<MethodAspect> aspects = Lists.newArrayList();
+
+  public void testSimpleCase()
+      throws NoSuchMethodException, InvocationTargetException, ErrorsException {
+    SimpleInterceptor interceptor = new SimpleInterceptor();
+    InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Simple.class);
+
+    aspects.add(new MethodAspect(any(), any(), interceptor));
+    ProxyFactory<Simple> factory = new ProxyFactory<Simple>(injectionPoint, aspects);
+
+    ConstructionProxy<Simple> constructionProxy = factory.create();
+
+    Simple simple = constructionProxy.newInstance();
+    simple.invoke();
+    assertTrue(simple.invoked);
+    assertTrue(interceptor.invoked);
+  }
+
+  static class Simple {
+    boolean invoked = false;
+    public void invoke() {
+      invoked = true;
+    }
+  }
+
+  static class SimpleInterceptor implements MethodInterceptor {
+
+    boolean invoked = false;
+
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      invoked = true;
+      return methodInvocation.proceed();
+    }
+  }
+
+  public void testInterceptOneMethod()
+      throws NoSuchMethodException, InvocationTargetException, ErrorsException {
+    SimpleInterceptor interceptor = new SimpleInterceptor();
+
+    aspects.add(new MethodAspect(only(Bar.class), annotatedWith(Intercept.class), interceptor));
+
+    ConstructionProxy<Foo> fooFactory
+        = new ProxyFactory<Foo>(InjectionPoint.forConstructorOf(Foo.class), aspects).create();
+    ConstructionProxy<Bar> barFactory
+        = new ProxyFactory<Bar>(InjectionPoint.forConstructorOf(Bar.class), aspects).create();
+
+    Foo foo = fooFactory.newInstance();
+    Bar bar = barFactory.newInstance();
+
+    foo.foo();
+    assertTrue(foo.fooCalled);
+    assertFalse(interceptor.invoked);
+
+    bar.bar();
+    assertTrue(bar.barCalled);
+    assertFalse(interceptor.invoked);
+
+    bar.intercepted();
+    assertTrue(bar.interceptedCalled);
+    assertTrue(interceptor.invoked);
+  }
+
+  static class Foo {
+    boolean fooCalled;
+    @Intercept
+    void foo() {
+      fooCalled = true;
+    }
+  }
+
+  static class Bar {
+
+    boolean barCalled;
+    void bar() {
+      barCalled = true;
+    }
+
+    boolean interceptedCalled;
+
+    @Intercept
+    void intercepted() {
+      interceptedCalled = true;
+    }
+  }
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @interface Intercept {}
+
+  public void testWithConstructorArguments()
+      throws InvocationTargetException, NoSuchMethodException, ErrorsException {
+    SimpleInterceptor interceptor = new SimpleInterceptor();
+
+    aspects.add(new MethodAspect(any(), any(), interceptor));
+    ProxyFactory<A> factory
+        = new ProxyFactory<A>(InjectionPoint.forConstructorOf(A.class), aspects);
+
+    ConstructionProxy<A> constructor = factory.create();
+
+    A a = constructor.newInstance(5);
+    a.a();
+    assertEquals(5, a.i);
+  }
+
+  public void testNotProxied()
+      throws NoSuchMethodException, InvocationTargetException, ErrorsException {
+    SimpleInterceptor interceptor = new SimpleInterceptor();
+
+    aspects.add(new MethodAspect(not(any()), not(any()), interceptor));
+    ProxyFactory<A> factory
+        = new ProxyFactory<A>(InjectionPoint.forConstructorOf(A.class), aspects);
+
+    ConstructionProxy<A> constructor = factory.create();
+
+    A a = constructor.newInstance(5);
+    assertEquals(A.class, a.getClass());
+  }
+
+  static class A {
+    final int i;
+    @Inject public A(int i) {
+      this.i = i;
+    }
+    public void a() {}
+  }
+
+  public void testMultipleInterceptors()
+      throws NoSuchMethodException, InvocationTargetException, ErrorsException {
+    DoubleInterceptor doubleInterceptor = new DoubleInterceptor();
+    CountingInterceptor countingInterceptor = new CountingInterceptor();
+
+    aspects.add(new MethodAspect(any(), any(), doubleInterceptor, countingInterceptor));
+    ProxyFactory<Counter> factory
+        = new ProxyFactory<Counter>(InjectionPoint.forConstructorOf(Counter.class), aspects);
+
+    ConstructionProxy<Counter> constructor = factory.create();
+
+    Counter counter = constructor.newInstance();
+    counter.inc();
+    assertEquals(2, counter.count);
+    assertEquals(2, countingInterceptor.count);
+  }
+
+  static class CountingInterceptor implements MethodInterceptor {
+
+    int count;
+
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      count++;
+      return methodInvocation.proceed();
+    }
+  }
+
+  static class DoubleInterceptor implements MethodInterceptor {
+
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      methodInvocation.proceed();
+      return methodInvocation.proceed();
+    }
+  }
+
+  static class Counter {
+    int count;
+    void inc() {
+      count++;
+    }
+  }
+}
diff --git a/core/test/com/google/inject/internal/UniqueAnnotationsTest.java b/core/test/com/google/inject/internal/UniqueAnnotationsTest.java
new file mode 100644
index 0000000..9676eca
--- /dev/null
+++ b/core/test/com/google/inject/internal/UniqueAnnotationsTest.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 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.inject.internal;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class UniqueAnnotationsTest extends TestCase {
+
+  @UniqueAnnotations.Internal(31) public Void unused;
+  
+  public void testEqualsHashCodeToString() {
+    Annotation actual = UniqueAnnotations.create(31);
+
+    Annotation expected = getClass().getFields()[0].getAnnotations()[0];
+
+    assertEquals(expected.toString(), actual.toString());
+    assertEquals(expected.hashCode(), actual.hashCode());
+    assertEquals(expected, actual);
+  }
+}
diff --git a/core/test/com/google/inject/internal/WeakKeySetTest.java b/core/test/com/google/inject/internal/WeakKeySetTest.java
new file mode 100644
index 0000000..4a81ebb
--- /dev/null
+++ b/core/test/com/google/inject/internal/WeakKeySetTest.java
@@ -0,0 +1,528 @@
+/**
+ * Copyright (C) 2014 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.inject.internal;
+
+import static com.google.inject.Asserts.awaitClear;
+import static com.google.inject.Asserts.awaitFullGc;
+import static com.google.inject.internal.WeakKeySetUtils.assertBlacklisted;
+import static com.google.inject.internal.WeakKeySetUtils.assertInSet;
+import static com.google.inject.internal.WeakKeySetUtils.assertNotBlacklisted;
+import static com.google.inject.internal.WeakKeySetUtils.assertNotInSet;
+import static com.google.inject.internal.WeakKeySetUtils.assertSourceNotInSet;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Scope;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding;
+import com.google.inject.spi.ProvisionListenerBinding;
+import com.google.inject.spi.ScopeBinding;
+import com.google.inject.spi.TypeConverterBinding;
+import com.google.inject.spi.TypeListenerBinding;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.ref.WeakReference;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests for {@link WeakKeySet}.
+ * <p>
+ * Multibinding specific tests can be found in MultibinderTest and MapBinderTest.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class WeakKeySetTest extends TestCase {
+
+  private WeakKeySet set;
+
+  @Override
+  protected void setUp() throws Exception {
+    set = new WeakKeySet(new Object());
+  }
+
+  public void testEviction() {
+    TestState state = new TestState();
+    Key<Integer> key = Key.get(Integer.class);
+    Object source = new Object();
+    
+    WeakReference<Key<Integer>> weakKeyRef = new WeakReference<Key<Integer>>(key);
+
+    set.add(key, state, source);
+    assertInSet(set, key, 1, source);
+
+    state = null;
+
+    awaitFullGc();
+
+    assertNotInSet(set, Key.get(Integer.class));
+
+    // Ensure there are no hanging references.
+    key = null;
+    awaitClear(weakKeyRef);
+  }
+  
+  public void testEviction_nullSource() {
+    TestState state = new TestState();
+    Key<Integer> key = Key.get(Integer.class);
+    Object source = null;
+    
+    WeakReference<Key<Integer>> weakKeyRef = new WeakReference<Key<Integer>>(key);
+
+    set.add(key, state, source);
+    assertInSet(set, key, 1, source);
+
+    state = null;
+
+    awaitFullGc();
+
+    assertNotInSet(set, Key.get(Integer.class));
+
+    // Ensure there are no hanging references.
+    key = null;
+    awaitClear(weakKeyRef);
+  }
+
+  public void testEviction_keyOverlap_2x() {
+    TestState state1 = new TestState();
+    TestState state2 = new TestState();
+    Key<Integer> key1 = Key.get(Integer.class);
+    Key<Integer> key2 = Key.get(Integer.class);
+    Object source1 = new Object();
+    Object source2 = new Object();
+
+    set.add(key1, state1, source1);
+    assertInSet(set, key1, 1, source1);
+
+    set.add(key2, state2, source2);
+    assertInSet(set, key2, 2, source1, source2);
+
+    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
+    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
+    WeakReference<Object> weakSource1Ref = new WeakReference<Object>(source1);
+    WeakReference<Object> weakSource2Ref = new WeakReference<Object>(source2);
+
+    Key<Integer> key = key1 = key2 = Key.get(Integer.class);
+    state1 = null;
+
+    awaitFullGc();
+
+    assertSourceNotInSet(set, key, source1);
+    assertInSet(set, key, 1, source2);
+
+    source1 = source2 = null;
+    
+    awaitClear(weakSource1Ref);
+    // Key1 will be referenced as the key in the sources backingSet and won't be
+    // GC'd.
+    
+    // Should not be GC'd until state2 goes away.
+    assertNotNull(weakSource2Ref.get());
+
+    state2 = null;
+
+    awaitFullGc();
+
+    assertNotInSet(set, key);
+
+    awaitClear(weakKey2Ref);
+    awaitClear(weakSource2Ref);
+    // Now that the backing set is emptied, key1 is released.
+    awaitClear(weakKey1Ref);
+  }
+  
+  public void testNoEviction_keyOverlap_2x() {
+    TestState state1 = new TestState();
+    TestState state2 = new TestState();
+    Key<Integer> key1 = Key.get(Integer.class);
+    Key<Integer> key2 = Key.get(Integer.class);
+    Object source1 = new Object();
+    Object source2 = new Object();
+
+    set.add(key1, state1, source1);
+    assertInSet(set, key1, 1, source1);
+
+    set.add(key2, state2, source2);
+    assertInSet(set, key2, 2, source1, source2);
+
+    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
+    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
+
+    Key<Integer> key = key1 = key2 = Key.get(Integer.class);
+
+    awaitFullGc();
+    assertInSet(set, key, 2, source1, source2);
+
+    // Ensure the keys don't get GC'd when states are still referenced. key1 will be present in the
+    // as the map key but key2 could be GC'd if the implementation does something wrong.
+    assertNotNull(weakKey1Ref.get());
+    assertNotNull(weakKey2Ref.get());
+  }
+
+  public void testEviction_keyAndSourceOverlap_null() {
+    TestState state1 = new TestState();
+    TestState state2 = new TestState();
+    Key<Integer> key1 = Key.get(Integer.class);
+    Key<Integer> key2 = Key.get(Integer.class);
+    Object source = null;
+
+    set.add(key1, state1, source);
+    assertInSet(set, key1, 1, source);
+
+    set.add(key2, state2, source);
+    // Same source so still only one value.
+    assertInSet(set, key2, 1, source);
+    assertInSet(set, key1, 1, source);
+
+    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
+    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
+    WeakReference<Object> weakSourceRef = new WeakReference<Object>(source);
+
+    Key<Integer> key = key1 = key2 = Key.get(Integer.class);
+    state1 = null;
+
+    awaitFullGc();
+    // Should still have a single source.
+    assertInSet(set, key, 1, source);
+
+    source = null;
+
+    awaitClear(weakSourceRef);
+    // Key1 will be referenced as the key in the sources backingSet and won't be
+    // GC'd.
+
+    state2 = null;
+
+    awaitFullGc();
+    assertNotInSet(set, key);
+
+    awaitClear(weakKey2Ref);
+    awaitClear(weakSourceRef);
+    // Now that the backing set is emptied, key1 is released.
+    awaitClear(weakKey1Ref);
+  }
+  
+  public void testEviction_keyAndSourceOverlap_nonNull() {
+    TestState state1 = new TestState();
+    TestState state2 = new TestState();
+    Key<Integer> key1 = Key.get(Integer.class);
+    Key<Integer> key2 = Key.get(Integer.class);
+    Object source = new Object();
+
+    set.add(key1, state1, source);
+    assertInSet(set, key1, 1, source);
+
+    set.add(key2, state2, source);
+    // Same source so still only one value.
+    assertInSet(set, key2, 1, source);
+
+    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
+    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
+    WeakReference<Object> weakSourceRef = new WeakReference<Object>(source);
+
+    Key<Integer> key = key1 = key2 = Key.get(Integer.class);
+    state1 = null;
+
+    awaitFullGc();
+
+ // Same source so still only one value.
+    assertInSet(set, key, 1, source);
+    assertInSet(set, key1, 1, source);
+    
+    source = null;
+
+    awaitFullGc();
+    assertNotNull(weakSourceRef.get());
+    // Key1 will be referenced as the key in the sources backingSet and won't be
+    // GC'd.
+
+    state2 = null;
+
+    awaitFullGc();
+
+    assertNotInSet(set, key);
+
+    awaitClear(weakKey2Ref);
+    awaitClear(weakSourceRef);
+    // Now that the backing set is emptied, key1 is released.
+    awaitClear(weakKey1Ref);
+  }
+
+  public void testEviction_keyOverlap_3x() {
+    TestState state1 = new TestState();
+    TestState state2 = new TestState();
+    TestState state3 = new TestState();
+    Key<Integer> key1 = Key.get(Integer.class);
+    Key<Integer> key2 = Key.get(Integer.class);
+    Key<Integer> key3 = Key.get(Integer.class);
+    Object source1 = new Object();
+    Object source2 = new Object();
+    Object source3 = new Object();
+
+    set.add(key1, state1, source1);
+    assertInSet(set, key1, 1, source1);
+
+    set.add(key2, state2, source2);
+    assertInSet(set, key1, 2, source1, source2);
+
+    set.add(key3, state3, source3);
+    assertInSet(set, key1, 3, source1, source2, source3);
+
+    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
+    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
+    WeakReference<Key<Integer>> weakKey3Ref = new WeakReference<Key<Integer>>(key3);
+    WeakReference<Object> weakSource1Ref = new WeakReference<Object>(source1);
+    WeakReference<Object> weakSource2Ref = new WeakReference<Object>(source2);
+    WeakReference<Object> weakSource3Ref = new WeakReference<Object>(source3);
+
+    Key<Integer> key = key1 = key2 = key3 = Key.get(Integer.class);
+    state1 = null;
+
+    awaitFullGc();
+    assertSourceNotInSet(set, key, source1);
+    assertInSet(set, key, 2, source2, source3);
+
+    source1 = null;
+    // Key1 will be referenced as the key in the sources backingSet and won't be
+    // GC'd.
+    awaitClear(weakSource1Ref);
+
+    state2 = null;
+    awaitFullGc();
+    assertSourceNotInSet(set, key, source2);
+    assertInSet(set, key, 1, source3);
+
+    awaitClear(weakKey2Ref);
+    
+    source2 = null;
+    awaitClear(weakSource2Ref);
+    // Key1 will be referenced as the key in the sources backingSet and won't be
+    // GC'd.
+
+    state3 = null;
+    awaitFullGc();
+    assertNotInSet(set, key);
+
+    awaitClear(weakKey3Ref);
+    source3 = null;
+    awaitClear(weakSource3Ref);
+    // Now that the backing set is emptied, key1 is released.
+    awaitClear(weakKey1Ref);
+  }
+
+  public void testWeakKeySet_integration() {
+    Injector parentInjector = Guice.createInjector(new AbstractModule() {
+          @Override protected void configure() {
+            bind(Integer.class).toInstance(4);
+          }
+        });
+    assertNotBlacklisted(parentInjector, Key.get(String.class));
+
+    Injector childInjector = parentInjector.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("bar");
+      }
+    });
+    WeakReference<Injector> weakRef = new WeakReference<Injector>(childInjector);
+    assertBlacklisted(parentInjector, Key.get(String.class));
+    
+    // Clear the ref, GC, and ensure that we are no longer blacklisting.
+    childInjector = null;
+    awaitClear(weakRef);
+    assertNotBlacklisted(parentInjector, Key.get(String.class));
+  }
+  
+  public void testWeakKeySet_integration_multipleChildren() {
+    Injector parentInjector = Guice.createInjector(new AbstractModule() {
+          @Override protected void configure() {
+            bind(Integer.class).toInstance(4);
+          }
+        });
+    assertNotBlacklisted(parentInjector, Key.get(String.class));
+    assertNotBlacklisted(parentInjector, Key.get(Long.class));
+
+    Injector childInjector1 = parentInjector.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("foo");
+      }
+    });
+    WeakReference<Injector> weakRef1 = new WeakReference<Injector>(childInjector1);
+    assertBlacklisted(parentInjector, Key.get(String.class));
+    assertNotBlacklisted(parentInjector, Key.get(Long.class));
+    
+    Injector childInjector2 = parentInjector.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(Long.class).toInstance(6L);
+      }
+    });
+    WeakReference<Injector> weakRef2 = new WeakReference<Injector>(childInjector2);
+    assertBlacklisted(parentInjector, Key.get(String.class));
+    assertBlacklisted(parentInjector, Key.get(Long.class));
+    
+    // Clear ref1, GC, and ensure that we still blacklist.
+    childInjector1 = null;
+    awaitClear(weakRef1);
+    assertNotBlacklisted(parentInjector, Key.get(String.class));
+    assertBlacklisted(parentInjector, Key.get(Long.class));
+
+    // Clear the ref, GC, and ensure that we are no longer blacklisting.
+    childInjector2 = null;
+    awaitClear(weakRef2);
+    assertNotBlacklisted(parentInjector, Key.get(String.class));
+    assertNotBlacklisted(parentInjector, Key.get(Long.class));
+  }
+  
+  public void testWeakKeySet_integration_multipleChildren_overlappingKeys() {
+    Injector parentInjector = Guice.createInjector(new AbstractModule() {
+          @Override protected void configure() {
+            bind(Integer.class).toInstance(4);
+          }
+        });
+    assertNotBlacklisted(parentInjector, Key.get(String.class));
+
+    Injector childInjector1 = parentInjector.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("foo");
+      }
+    });
+    WeakReference<Injector> weakRef1 = new WeakReference<Injector>(childInjector1);
+    assertBlacklisted(parentInjector, Key.get(String.class));
+    
+    Injector childInjector2 = parentInjector.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("bar");
+      }
+    });
+    WeakReference<Injector> weakRef2 = new WeakReference<Injector>(childInjector2);
+    assertBlacklisted(parentInjector, Key.get(String.class));
+    
+    // Clear ref1, GC, and ensure that we still blacklist.
+    childInjector1 = null;
+    awaitClear(weakRef1);
+    assertBlacklisted(parentInjector, Key.get(String.class));
+
+    // Clear the ref, GC, and ensure that we are no longer blacklisting.
+    childInjector2 = null;
+    awaitClear(weakRef2);
+    assertNotBlacklisted(parentInjector, Key.get(String.class));
+  }
+
+  private static class TestState implements State {
+    public State parent() {
+      return new TestState();
+    }
+
+    public <T> BindingImpl<T> getExplicitBinding(Key<T> key) {
+      return null;
+    }
+
+    public Map<Key<?>, Binding<?>> getExplicitBindingsThisLevel() {
+      throw new UnsupportedOperationException();
+    }
+
+    public void putBinding(Key<?> key, BindingImpl<?> binding) {
+      throw new UnsupportedOperationException();
+    }
+
+    public ScopeBinding getScopeBinding(Class<? extends Annotation> scopingAnnotation) {
+      return null;
+    }
+
+    public void putScopeBinding(Class<? extends Annotation> annotationType, ScopeBinding scope) {
+      throw new UnsupportedOperationException();
+    }
+
+    public void addConverter(TypeConverterBinding typeConverterBinding) {
+      throw new UnsupportedOperationException();
+    }
+
+    public TypeConverterBinding getConverter(String stringValue, TypeLiteral<?> type, Errors errors,
+        Object source) {
+      throw new UnsupportedOperationException();
+    }
+
+    public Iterable<TypeConverterBinding> getConvertersThisLevel() {
+      return ImmutableSet.of();
+    }
+
+    /*if[AOP]*/
+    public void addMethodAspect(MethodAspect methodAspect) {
+      throw new UnsupportedOperationException();
+    }
+
+    public ImmutableList<MethodAspect> getMethodAspects() {
+      return ImmutableList.of();
+    }
+    /*end[AOP]*/
+
+    public void addTypeListener(TypeListenerBinding typeListenerBinding) {
+      throw new UnsupportedOperationException();
+    }
+
+    public List<TypeListenerBinding> getTypeListenerBindings() {
+      return ImmutableList.of();
+    }
+
+    public void addProvisionListener(ProvisionListenerBinding provisionListenerBinding) {
+      throw new UnsupportedOperationException();
+    }
+
+    public List<ProvisionListenerBinding> getProvisionListenerBindings() {
+      return ImmutableList.of();
+    }
+
+    public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) {
+      throw new UnsupportedOperationException();
+    }
+
+    public List<ModuleAnnotatedMethodScannerBinding> getScannerBindings() {
+      return ImmutableList.of();
+    }
+
+    public void blacklist(Key<?> key, State state, Object source) {
+    }
+
+    public boolean isBlacklisted(Key<?> key) {
+      return true;
+    }
+
+    public Set<Object> getSourcesForBlacklistedKey(Key<?> key) {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object lock() {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object singletonCreationLock() {
+      throw new UnsupportedOperationException();
+    }
+
+    public Map<Class<? extends Annotation>, Scope> getScopes() {
+      return ImmutableMap.of();
+    }
+  }
+}
diff --git a/core/test/com/google/inject/internal/WeakKeySetUtils.java b/core/test/com/google/inject/internal/WeakKeySetUtils.java
new file mode 100644
index 0000000..b023aa1
--- /dev/null
+++ b/core/test/com/google/inject/internal/WeakKeySetUtils.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright (C) 2014 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.inject.internal;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import com.google.inject.Injector;
+import com.google.inject.Key;
+
+import java.util.Set;
+
+/**
+ * Utilities for verifying com.google.inject.internal.WeakKeySet is not leaking memory.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public final class WeakKeySetUtils {
+
+  private WeakKeySetUtils() {}
+
+  public static void assertBlacklisted(Injector injector, Key<?> key) {
+    assertBlacklistState(injector, key, true);
+  }
+
+  public static void assertNotBlacklisted(Injector injector, Key<?> key) {
+    assertBlacklistState(injector, key, false);
+  }
+
+  public static void assertNotInSet(WeakKeySet set, Key<?> key) {
+    // if we're expecting it to not be in the set, loop around and wait for threads to run.
+    for (int i = 0; i < 10; i++) {
+      if (!set.contains(key)) {
+        break;
+      }
+      sleep();
+    }
+    assertFalse(set.contains(key));
+    assertNull(set.getSources(Key.get(Integer.class)));
+  }
+
+  public static void assertInSet(WeakKeySet set, Key<?> key, int expectedSources,
+      Object... sources) {
+    assertTrue(set.contains(key));
+    assertEquals(expectedSources, set.getSources(key).size());
+    for (Object source : sources) {
+      assertTrue("didn't contain source: " + source, set.getSources(key).contains(source));
+    }
+  }
+
+  public static void assertSourceNotInSet(WeakKeySet set, Key<?> key, Object source) {
+    // if we're expecting it to not be a source, loop around and wait for threads to run.
+    for (int i = 0; i < 10; i++) {
+      Set<Object> sources = set.getSources(key);
+      assertNotNull("expected at least one source", source);
+      if (!sources.contains(source)) {
+        break;
+      }
+      sleep();
+    }
+    Set<Object> sources = set.getSources(key);
+    assertNotNull("expected at least one source", source);
+    assertFalse(sources.contains(source));
+  }
+
+  private static void assertBlacklistState(Injector injector, Key<?> key, boolean isBlacklisted) {
+    // if we're expecting it to not be blacklisted, loop around and wait for threads to run.
+    if (!isBlacklisted) {
+      for (int i = 0; i < 10; i++) {
+        if (!((InjectorImpl) injector).state.isBlacklisted(key)) {
+          break;
+        }
+        sleep();
+      }
+    }
+    assertEquals(isBlacklisted, ((InjectorImpl) injector).state.isBlacklisted(key));
+  }
+
+  private static void sleep() {
+    try {
+      Thread.sleep(1000);
+    } catch (InterruptedException e) {
+      throw new RuntimeException(e);
+    }
+    Thread.yield();
+  }
+}
diff --git a/core/test/com/google/inject/internal/util/LineNumbersTest.java b/core/test/com/google/inject/internal/util/LineNumbersTest.java
new file mode 100644
index 0000000..3b23f15
--- /dev/null
+++ b/core/test/com/google/inject/internal/util/LineNumbersTest.java
@@ -0,0 +1,146 @@
+/**
+ * Copyright (C) 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.inject.internal.util;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.matcher.Matchers;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Modifier;
+
+import javax.inject.Inject;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class LineNumbersTest extends TestCase {
+
+  public void testLineNumbers() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(A.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for " + B.class.getName() + " was bound.",
+          "for parameter 0 at " + A.class.getName() + ".<init>(LineNumbersTest.java:",
+          "at " + LineNumbersTest.class.getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  static class A {
+    @Inject A(B b) {}
+  }
+  public interface B {}
+
+  /*if[AOP]*/
+  public void testCanHandleLineNumbersForGuiceGeneratedClasses() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bindInterceptor(Matchers.only(A.class), Matchers.any(),
+              new org.aopalliance.intercept.MethodInterceptor() {
+                public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) {
+                  return null;
+                }
+              });
+
+          bind(A.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for " + B.class.getName() + " was bound.",
+          "for parameter 0 at " + A.class.getName() + ".<init>(LineNumbersTest.java:",
+          "at " + LineNumbersTest.class.getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+
+  static class GeneratingClassLoader extends ClassLoader {
+    static String name = "__generated";
+
+    GeneratingClassLoader() {
+      super(B.class.getClassLoader());
+    }
+
+    Class<?> generate() {
+      org.objectweb.asm.ClassWriter cw =
+          new org.objectweb.asm.ClassWriter(org.objectweb.asm.ClassWriter.COMPUTE_MAXS);
+      cw.visit(org.objectweb.asm.Opcodes.V1_5,
+          Modifier.PUBLIC, name, null,
+          org.objectweb.asm.Type.getInternalName(Object.class), null);
+
+      String sig = "("+org.objectweb.asm.Type.getDescriptor(B.class)+")V";
+
+      org.objectweb.asm.MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "<init>", sig, null, null);
+
+      mv.visitAnnotation(org.objectweb.asm.Type.getDescriptor(Inject.class), true);
+      mv.visitCode();
+      mv.visitVarInsn(org.objectweb.asm.Opcodes.ALOAD, 0);
+      mv.visitMethodInsn(org.objectweb.asm.Opcodes.INVOKESPECIAL,
+          org.objectweb.asm.Type.getInternalName(Object.class), "<init>", "()V" );
+      mv.visitInsn(org.objectweb.asm.Opcodes.RETURN);
+      mv.visitMaxs(0, 0);
+      mv.visitEnd();
+      cw.visitEnd();
+
+      byte[] buf = cw.toByteArray();
+
+      return defineClass(name.replace('/', '.'), buf, 0, buf.length);
+    }
+  }
+
+  public void testUnavailableByteCodeShowsUnknownSource() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(new GeneratingClassLoader().generate());
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for " + B.class.getName() + " was bound.",
+          "for parameter 0 at " + GeneratingClassLoader.name + ".<init>(Unknown Source)",
+          "at " + LineNumbersTest.class.getName(), getDeclaringSourcePart(getClass()));
+    }
+  }
+  
+  public void testGeneratedClassesCanSucceed() {
+    final Class<?> generated = new GeneratingClassLoader().generate();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(generated);
+        bind(B.class).toInstance(new B() {});
+      }
+    });
+    Object instance = injector.getInstance(generated);
+    assertEquals(instance.getClass(), generated);
+  }
+  /*end[AOP]*/
+}
diff --git a/core/test/com/google/inject/matcher/MatcherTest.java b/core/test/com/google/inject/matcher/MatcherTest.java
new file mode 100644
index 0000000..58fbdf2
--- /dev/null
+++ b/core/test/com/google/inject/matcher/MatcherTest.java
@@ -0,0 +1,178 @@
+/**
+ * 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 com.google.inject.matcher;
+
+import static com.google.inject.Asserts.assertEqualWhenReserialized;
+import static com.google.inject.Asserts.assertEqualsBothWays;
+import static com.google.inject.matcher.Matchers.annotatedWith;
+import static com.google.inject.matcher.Matchers.any;
+import static com.google.inject.matcher.Matchers.identicalTo;
+import static com.google.inject.matcher.Matchers.inPackage;
+import static com.google.inject.matcher.Matchers.inSubpackage;
+import static com.google.inject.matcher.Matchers.not;
+import static com.google.inject.matcher.Matchers.only;
+import static com.google.inject.matcher.Matchers.returns;
+import static com.google.inject.matcher.Matchers.subclassesOf;
+
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+import java.util.AbstractList;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+
+public class MatcherTest extends TestCase {
+
+  public void testAny() {
+    assertTrue(any().matches(null));
+    assertEquals("any()", any().toString());
+    assertEqualsBothWays(any(), any());
+    assertFalse(any().equals(not(any())));
+  }
+
+  public void testNot() {
+    assertFalse(not(any()).matches(null));
+    assertEquals("not(any())", not(any()).toString());
+    assertEqualsBothWays(not(any()), not(any()));
+    assertFalse(not(any()).equals(any()));
+  }
+
+  public void testAnd() {
+    assertTrue(any().and(any()).matches(null));
+    assertFalse(any().and(not(any())).matches(null));
+    assertEquals("and(any(), any())", any().and(any()).toString());
+    assertEqualsBothWays(any().and(any()), any().and(any()));
+    assertFalse(any().and(any()).equals(not(any())));
+  }
+
+  public void testOr() {
+    assertTrue(any().or(not(any())).matches(null));
+    assertFalse(not(any()).or(not(any())).matches(null));
+    assertEquals("or(any(), any())", any().or(any()).toString());
+    assertEqualsBothWays(any().or(any()), any().or(any()));
+    assertFalse(any().or(any()).equals(not(any())));
+  }
+
+  public void testAnnotatedWith() {
+    assertTrue(annotatedWith(Foo.class).matches(Bar.class));
+    assertFalse(annotatedWith(Foo.class).matches(
+        MatcherTest.class.getMethods()[0]));
+    assertEquals("annotatedWith(Foo.class)", annotatedWith(Foo.class).toString());
+    assertEqualsBothWays(annotatedWith(Foo.class), annotatedWith(Foo.class));
+    assertFalse(annotatedWith(Foo.class).equals(annotatedWith(Named.class)));
+
+    try {
+      annotatedWith(Baz.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void testSubclassesOf() {
+    assertTrue(subclassesOf(Runnable.class).matches(Runnable.class));
+    assertTrue(subclassesOf(Runnable.class).matches(MyRunnable.class));
+    assertFalse(subclassesOf(Runnable.class).matches(Object.class));
+    assertEquals("subclassesOf(Runnable.class)", subclassesOf(Runnable.class).toString());
+    assertEqualsBothWays(subclassesOf(Runnable.class), subclassesOf(Runnable.class));
+    assertFalse(subclassesOf(Runnable.class).equals(subclassesOf(Object.class)));
+  }
+
+  public void testOnly() {
+    assertTrue(only(1000).matches(1000));
+    assertFalse(only(1).matches(1000));
+    assertEquals("only(1)", only(1).toString());
+    assertEqualsBothWays(only(1), only(1));
+    assertFalse(only(1).equals(only(2)));
+  }
+
+  @SuppressWarnings("UnnecessaryBoxing")
+  public void testIdenticalTo() {
+    Object o = new Object();
+    assertEquals("identicalTo(1)", identicalTo(1).toString());
+    assertTrue(identicalTo(o).matches(o));
+    assertFalse(identicalTo(o).matches(new Object()));
+    assertEqualsBothWays(identicalTo(o), identicalTo(o));
+    assertFalse(identicalTo(1).equals(identicalTo(new Integer(1))));
+  }
+
+  public void testInPackage() {
+    Package matchersPackage = Matchers.class.getPackage();
+    assertEquals("inPackage(com.google.inject.matcher)", inPackage(matchersPackage).toString());
+    assertTrue(inPackage(matchersPackage).matches(MatcherTest.class));
+    assertFalse(inPackage(matchersPackage).matches(Object.class));
+    assertEqualsBothWays(inPackage(matchersPackage), inPackage(matchersPackage));
+    assertFalse(inPackage(matchersPackage).equals(inPackage(Object.class.getPackage())));
+  }
+
+  public void testInSubpackage() {
+    String stringPackageName = String.class.getPackage().getName();
+    assertEquals("inSubpackage(java.lang)", inSubpackage(stringPackageName).toString());
+    assertTrue(inSubpackage(stringPackageName).matches(Object.class));
+    assertTrue(inSubpackage(stringPackageName).matches(Method.class));
+    assertFalse(inSubpackage(stringPackageName).matches(Matchers.class));
+    assertFalse(inSubpackage("jav").matches(Object.class));
+    assertEqualsBothWays(inSubpackage(stringPackageName), inSubpackage(stringPackageName));
+    assertFalse(inSubpackage(stringPackageName).equals(inSubpackage(Matchers.class.getPackage().getName())));
+  }
+
+  public void testReturns() throws NoSuchMethodException {
+    Matcher<Method> predicate = returns(only(String.class));
+    assertTrue(predicate.matches(
+        Object.class.getMethod("toString")));
+    assertFalse(predicate.matches(
+        Object.class.getMethod("hashCode")));
+    assertEquals("returns(only(class java.lang.String))", returns(only(String.class)).toString());
+    assertEqualsBothWays(predicate, returns(only(String.class)));
+    assertFalse(predicate.equals(returns(only(Integer.class))));
+  }
+
+  public void testSerialization() throws IOException {
+    assertEqualWhenReserialized(any());
+    assertEqualWhenReserialized(not(any()));
+    assertEqualWhenReserialized(annotatedWith(Named.class));
+    assertEqualWhenReserialized(annotatedWith(Names.named("foo")));
+    assertEqualWhenReserialized(only("foo"));
+    assertEqualWhenReserialized(identicalTo(Object.class));
+    assertEqualWhenReserialized(inPackage(String.class.getPackage()));
+    assertEqualWhenReserialized(inSubpackage(String.class.getPackage().getName()));
+    assertEqualWhenReserialized(returns(any()));
+    assertEqualWhenReserialized(subclassesOf(AbstractList.class));
+    assertEqualWhenReserialized(only("a").or(only("b")));
+    assertEqualWhenReserialized(only("a").and(only("b")));
+  }
+
+  static abstract class MyRunnable implements Runnable {}
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @interface Foo {}
+
+  @Foo
+  static class Bar {}
+
+  @interface Baz {}
+
+  @Baz
+  static class Car {}
+}
diff --git a/core/test/com/google/inject/name/NamedEquivalanceTest.java b/core/test/com/google/inject/name/NamedEquivalanceTest.java
new file mode 100644
index 0000000..36dee0c
--- /dev/null
+++ b/core/test/com/google/inject/name/NamedEquivalanceTest.java
@@ -0,0 +1,258 @@
+/**
+ * Copyright (C) 2010 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.inject.name;
+
+import static com.google.inject.Asserts.assertContains;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.ConfigurationException;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+
+import junit.framework.TestCase;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.util.Properties;
+
+/**
+ * Tests that {@code javax.inject.Named} and {@code com.google.inject.name.Named} are completely
+ * interchangeable: bindings for one can be used to inject the other.
+ * 
+ * @author cgdecker@gmail.com (Colin Decker)
+ */
+public class NamedEquivalanceTest extends TestCase {
+
+  private static final Module GUICE_BINDING_MODULE = moduleWithAnnotation(Names.named("foo"));
+  private static final Module JSR330_BINDING_MODULE = moduleWithAnnotation(new JsrNamed("foo"));
+  private static final Module GUICE_PROVIDER_METHOD_MODULE = getGuiceBindingProviderMethodModule();
+  private static final Module JSR330_PROVIDER_METHOD_MODULE = getJsr330BindingProviderMethodModule();
+
+  public void testKeysCreatedWithDifferentTypesAreEqual() {
+    assertEquals(keyForAnnotation(new GuiceNamed("foo")), keyForAnnotation(new JsrNamed("foo")));
+    assertEquals(keyForAnnotation(Names.named("foo")), keyForAnnotation(new GuiceNamed("foo")));
+    assertEquals(keyForAnnotation(Names.named("foo")), keyForAnnotation(new JsrNamed("foo")));
+
+    assertEquals(keyForAnnotationType(com.google.inject.name.Named.class),
+        keyForAnnotationType(javax.inject.Named.class));
+  }
+
+  private static Key<String> keyForAnnotation(Annotation annotation) {
+    return Key.get(String.class, annotation);
+  }
+  
+  private static Key<String> keyForAnnotationType(Class<? extends Annotation> annotationType) {
+    return Key.get(String.class, annotationType);
+  }
+
+  public void testBindingWithNamesCanInjectBothTypes() {
+    assertInjectionsSucceed(GUICE_BINDING_MODULE);
+  }
+
+  public void testBindingWithJsr330AnnotationCanInjectBothTypes() {
+    assertInjectionsSucceed(JSR330_BINDING_MODULE);
+  }
+
+  public void testBindingWithGuiceNamedAnnotatedProviderMethodCanInjectBothTypes() {
+    assertInjectionsSucceed(GUICE_PROVIDER_METHOD_MODULE);
+  }
+
+  public void testBindingWithJsr330NamedAnnotatedProviderMethodCanInjectBothTypes() {
+    assertInjectionsSucceed(JSR330_PROVIDER_METHOD_MODULE);
+  }
+
+  public void testBindingDifferentTypesWithSameValueIsIgnored() {
+    assertDuplicateBinding(GUICE_BINDING_MODULE, JSR330_BINDING_MODULE, false);
+    assertDuplicateBinding(JSR330_BINDING_MODULE, GUICE_BINDING_MODULE, false);
+  }
+
+  public void testBindingDifferentTypesWithSameValueIsAnErrorWithProviderMethods() {
+    assertDuplicateBinding(GUICE_PROVIDER_METHOD_MODULE, JSR330_PROVIDER_METHOD_MODULE, true);
+    assertDuplicateBinding(JSR330_PROVIDER_METHOD_MODULE, GUICE_PROVIDER_METHOD_MODULE, true);
+  }
+
+  public void testBindingDifferentTypesWithSameValueIsAnErrorMixed() {
+    assertDuplicateBinding(GUICE_BINDING_MODULE, JSR330_PROVIDER_METHOD_MODULE, true);
+    assertDuplicateBinding(JSR330_BINDING_MODULE, GUICE_PROVIDER_METHOD_MODULE, true);
+  }
+
+  public void testMissingBindingForGuiceNamedUsesSameTypeInErrorMessage() {
+    assertMissingBindingErrorMessageUsesType(GuiceNamedClient.class);
+  }
+
+  public void testMissingBindingForJsr330NamedUsesSameTypeInErrorMessage() {
+    assertMissingBindingErrorMessageUsesType(Jsr330NamedClient.class);
+  }
+
+  public void testBindPropertiesWorksWithJsr330() {
+    assertInjectionsSucceed(new AbstractModule() {
+      @Override protected void configure() {
+        Properties properties = new Properties();
+        properties.put("foo", "bar");
+        Names.bindProperties(binder(), properties);
+      }
+    });
+  }
+
+  private static void assertMissingBindingErrorMessageUsesType(Class<?> clientType) {
+    try {
+      Guice.createInjector().getInstance(clientType);
+      fail("should have thrown ConfigurationException");
+    } catch (ConfigurationException e) {
+      assertContains(e.getMessage(),
+          "No implementation for java.lang.String annotated with @com.google.inject.name.Named(value=foo) was bound.");
+    }
+  }
+
+  private static void assertDuplicateBinding(Module a, Module b, boolean fails) {
+    try {
+      Guice.createInjector(a, b);
+      if(fails) {
+        fail("should have thrown CreationException");
+      }
+    } catch (CreationException e) {
+      if(fails) {
+        assertContains(e.getMessage(),
+            "A binding to java.lang.String annotated with @com.google.inject.name.Named(value=foo) was already configured");
+      } else {
+        throw e;
+      }
+    }
+  }
+
+  private static Module moduleWithAnnotation(final Annotation annotation) {
+    return new AbstractModule() {
+      @Override protected void configure() {
+        bindConstant().annotatedWith(annotation).to("bar");
+      }
+    };
+  }
+
+  private static void assertInjectionsSucceed(Module module) {
+    Injector injector = Guice.createInjector(module);
+    assertInjected(injector.getInstance(GuiceNamedClient.class), injector
+        .getInstance(Jsr330NamedClient.class));
+  }
+
+  private static void assertInjected(GuiceNamedClient guiceClient, Jsr330NamedClient jsr330Client) {
+    assertEquals("bar", guiceClient.foo);
+    assertEquals("bar", jsr330Client.foo);
+  }
+
+  private static Module getJsr330BindingProviderMethodModule() {
+    return new AbstractModule() {
+      @Override protected void configure() {}
+      @SuppressWarnings("unused") @Provides @javax.inject.Named("foo") String provideFoo() {
+        return "bar";
+      }
+    };
+  }
+
+  private static Module getGuiceBindingProviderMethodModule() {
+    return new AbstractModule() {
+      @Override protected void configure() {}
+      @SuppressWarnings("unused") @Provides @Named("foo") String provideFoo() {
+        return "bar";
+      }
+    };
+  }
+
+  private static class GuiceNamedClient {
+    @Inject @Named("foo") String foo;
+  }
+
+  private static class Jsr330NamedClient {
+    @Inject @javax.inject.Named("foo") String foo;
+  }
+
+  private static class JsrNamed implements javax.inject.Named, Serializable {
+    private final String value;
+
+    public JsrNamed(String value) {
+      this.value = value;
+    }
+
+    public String value() {
+      return this.value;
+    }
+
+    public int hashCode() {
+      // This is specified in java.lang.Annotation.
+      return (127 * "value".hashCode()) ^ value.hashCode();
+    }
+
+    public boolean equals(Object o) {
+      if (!(o instanceof javax.inject.Named)) {
+        return false;
+      }
+
+      javax.inject.Named other = (javax.inject.Named) o;
+      return value.equals(other.value());
+    }
+
+    public String toString() {
+      return "@" + javax.inject.Named.class.getName() + "(value=" + value + ")";
+    }
+
+    public Class<? extends Annotation> annotationType() {
+      return javax.inject.Named.class;
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  private static class GuiceNamed implements com.google.inject.name.Named, Serializable {
+    private final String value;
+    
+    public GuiceNamed(String value) {
+      this.value = value;
+    }
+    
+    public String value() {
+      return this.value;
+    }
+    
+    public int hashCode() {
+      // This is specified in java.lang.Annotation.
+      return (127 * "value".hashCode()) ^ value.hashCode();
+    }
+
+    public boolean equals(Object o) {
+      if (!(o instanceof com.google.inject.name.Named)) {
+        return false;
+      }
+
+      com.google.inject.name.Named other = (com.google.inject.name.Named) o;
+      return value.equals(other.value());
+    }
+
+    public String toString() {
+      return "@" + com.google.inject.name.Named.class.getName() + "(value=" + value + ")";
+    }
+
+    public Class<? extends Annotation> annotationType() {
+      return com.google.inject.name.Named.class;
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+}
diff --git a/core/test/com/google/inject/name/NamesTest.java b/core/test/com/google/inject/name/NamesTest.java
new file mode 100644
index 0000000..0df3513
--- /dev/null
+++ b/core/test/com/google/inject/name/NamesTest.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright (C) 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.inject.name;
+
+import static com.google.inject.Asserts.assertEqualWhenReserialized;
+import static com.google.inject.Asserts.assertEqualsBothWays;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class NamesTest extends TestCase {
+
+  @Named("foo") private String foo;
+  private Named namedFoo;
+  
+  protected void setUp() throws Exception {
+    super.setUp();
+    namedFoo = getClass().getDeclaredField("foo").getAnnotation(Named.class);
+  }
+
+  public void testConsistentEqualsAndHashcode() {
+    Named actual = Names.named("foo");
+    assertEqualsBothWays(namedFoo, actual);
+    assertEquals(namedFoo.toString(), actual.toString());
+  }
+
+  public void testNamedIsSerializable() throws IOException {
+    assertEqualWhenReserialized(Names.named("foo"));
+  }
+
+  public void testBindPropertiesUsingProperties() {
+    final Properties teams = new Properties();
+    teams.setProperty("SanJose", "Sharks");
+    teams.setProperty("Edmonton", "Oilers");
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        Names.bindProperties(binder(), teams);
+      }
+    });
+
+    assertEquals("Sharks", injector.getInstance(Key.get(String.class, Names.named("SanJose"))));
+    assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton"))));
+  }
+
+  public void testBindPropertiesUsingMap() {
+    final Map<String, String> properties = ImmutableMap.of(
+        "SanJose", "Sharks", "Edmonton", "Oilers");
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        Names.bindProperties(binder(), properties);
+      }
+    });
+
+    assertEquals("Sharks", injector.getInstance(Key.get(String.class, Names.named("SanJose"))));
+    assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton"))));
+  }
+
+  public void testBindPropertiesIncludesInheritedProperties() {
+    Properties defaults = new Properties();
+    defaults.setProperty("Edmonton", "Eskimos");
+    defaults.setProperty("Regina", "Pats");
+
+    final Properties teams = new Properties(defaults);
+    teams.setProperty("SanJose", "Sharks");
+    teams.setProperty("Edmonton", "Oilers");
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        Names.bindProperties(binder(), teams);
+      }
+    });
+
+    assertEquals("Pats", injector.getInstance(Key.get(String.class, Names.named("Regina"))));
+    assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton"))));
+    assertEquals("Sharks", injector.getInstance(Key.get(String.class, Names.named("SanJose"))));
+
+    try {
+      injector.getInstance(Key.get(String.class, Names.named("Calgary")));
+      fail();
+    } catch (RuntimeException expected) {
+    }
+  }
+}
diff --git a/core/test/com/google/inject/spi/BindingTargetVisitorTest.java b/core/test/com/google/inject/spi/BindingTargetVisitorTest.java
new file mode 100644
index 0000000..7740551
--- /dev/null
+++ b/core/test/com/google/inject/spi/BindingTargetVisitorTest.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import junit.framework.TestCase;
+
+/**
+ * Simple little test that should compile. Ensures that wildcards on the
+ * generics are correct.
+ *
+ * @author phopkins@gmail.com
+ */
+public class BindingTargetVisitorTest extends TestCase {
+  public void testBindingTargetVisitorTypeTest() throws Exception {
+    Injector injector = Guice.createInjector();
+    for (Binding<?> binding : injector.getBindings().values()) {
+      binding.acceptTargetVisitor(new DefaultBindingTargetVisitor<Object, Object>() {});
+    }
+  }
+}
diff --git a/core/test/com/google/inject/spi/ElementApplyToTest.java b/core/test/com/google/inject/spi/ElementApplyToTest.java
new file mode 100644
index 0000000..d483ba4
--- /dev/null
+++ b/core/test/com/google/inject/spi/ElementApplyToTest.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Module;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class ElementApplyToTest extends ElementsTest {
+
+  @Override
+  protected void checkModule(Module module, ElementVisitor<?>... visitors) {
+    // convert from module to elements and back
+    super.checkModule(Elements.getModule(Elements.getElements(module)), visitors);
+  }
+}
\ No newline at end of file
diff --git a/core/test/com/google/inject/spi/ElementSourceTest.java b/core/test/com/google/inject/spi/ElementSourceTest.java
new file mode 100644
index 0000000..93fbeac
--- /dev/null
+++ b/core/test/com/google/inject/spi/ElementSourceTest.java
@@ -0,0 +1,175 @@
+package com.google.inject.spi;
+
+import static com.google.inject.internal.InternalFlags.getIncludeStackTraceOption;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Module;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.List;
+
+/**
+ * Tests for {@link ElementSource}.
+ */
+public class ElementSourceTest extends TestCase {
+
+  private static final StackTraceElement BINDER_INSTALL = 
+      new StackTraceElement("com.google.inject.spi.Elements$RecordingBinder", "install", 
+          "Unknown Source", 234 /* line number*/);
+  
+  public void testCallStackSize() {
+    ModuleSource moduleSource = createModuleSource();
+    StackTraceElement[] bindingCallStack = new StackTraceElement[3];
+    bindingCallStack[0] = new StackTraceElement(
+        "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 200);
+    bindingCallStack[1] = new StackTraceElement(
+        "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 100);
+    bindingCallStack[2] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$C", "configure", "Unknown Source", 100);
+    ElementSource elementSource = new ElementSource(
+        null /* No original element source */, "" /* Don't care */, moduleSource, bindingCallStack);
+    assertEquals(10 /* call stack size */, elementSource.getStackTrace().length);
+  }  
+
+  public void testGetCallStack_IntegrationTest() throws Exception {
+    List<Element> elements = Elements.getElements(new A());
+    for (Element element : elements) {
+      if (element instanceof Binding) {
+        Binding<?> binding = (Binding<?>) element;
+        Class<? extends Annotation> annotationType = binding.getKey().getAnnotationType();
+        if (annotationType != null && annotationType.equals(SampleAnnotation.class)) {
+          ElementSource elementSource = (ElementSource) binding.getSource();
+          List<String> moduleClassNames = elementSource.getModuleClassNames();
+          // Check module class names
+          // Module C
+          assertEquals("com.google.inject.spi.ElementSourceTest$C", moduleClassNames.get(0));
+          // Module B
+          assertEquals("com.google.inject.spi.ElementSourceTest$B", moduleClassNames.get(1));
+          // Module A
+          assertEquals("com.google.inject.spi.ElementSourceTest$A", moduleClassNames.get(2));
+          StackTraceElement[] callStack = elementSource.getStackTrace();
+          switch(getIncludeStackTraceOption()) {
+            case OFF:
+              // Check declaring source
+              StackTraceElement stackTraceElement = 
+                  (StackTraceElement) elementSource.getDeclaringSource();
+              assertEquals(new StackTraceElement(
+                  "com.google.inject.spi.ElementSourceTest$C", "configure", null, -1), 
+                  stackTraceElement);
+              // Check call stack
+              assertEquals(0, callStack.length);
+              return;
+            case ONLY_FOR_DECLARING_SOURCE:
+                // Check call stack
+                assertEquals(0, callStack.length);
+                return;
+            case COMPLETE:
+              // Check call stack
+              int skippedCallStackSize = new Throwable().getStackTrace().length - 1;
+              assertEquals(skippedCallStackSize + 15, elementSource.getStackTrace().length);
+              assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+                  callStack[0].getClassName());
+              assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+                  callStack[1].getClassName());
+              assertEquals("com.google.inject.AbstractModule",
+                  callStack[2].getClassName());
+              // Module C
+              assertEquals("com.google.inject.spi.ElementSourceTest$C",
+                  callStack[3].getClassName());
+              assertEquals("configure",
+                  callStack[3].getMethodName());
+              assertEquals("Unknown Source",
+                  callStack[3].getFileName());
+              assertEquals("com.google.inject.AbstractModule",
+                  callStack[4].getClassName());
+              assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+                  callStack[5].getClassName());
+              // Module B
+              assertEquals("com.google.inject.spi.ElementSourceTest$B",
+                  callStack[6].getClassName());
+              assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+                  callStack[7].getClassName());
+              // Module A
+              assertEquals("com.google.inject.AbstractModule",
+                  callStack[8].getClassName());
+              assertEquals("com.google.inject.spi.ElementSourceTest$A",
+                  callStack[9].getClassName());
+              assertEquals("com.google.inject.AbstractModule",
+                  callStack[10].getClassName());
+              assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+                  callStack[11].getClassName());
+              assertEquals("com.google.inject.spi.Elements",
+                  callStack[12].getClassName());
+              assertEquals("com.google.inject.spi.Elements",
+                  callStack[13].getClassName());
+              assertEquals("com.google.inject.spi.ElementSourceTest",
+                  callStack[14].getClassName());
+              // Check modules index
+              List<Integer> indexes = elementSource.getModuleConfigurePositionsInStackTrace();
+              assertEquals((int) indexes.get(0), 4);
+              assertEquals((int) indexes.get(1), 6);
+              assertEquals((int) indexes.get(2), 10);
+              return;
+          }
+        }
+      }
+    }
+    fail("The test should not reach this line.");
+  }  
+
+  private ModuleSource createModuleSource() {
+    // First module
+    StackTraceElement[] partialCallStack = new StackTraceElement[1];
+    partialCallStack[0] = BINDER_INSTALL;    
+    ModuleSource moduleSource = new ModuleSource(new A(), partialCallStack);
+    // Second module 
+    partialCallStack = new StackTraceElement[2];
+    partialCallStack[0] = BINDER_INSTALL;
+    partialCallStack[1] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100);
+    moduleSource = moduleSource.createChild(new B(), partialCallStack);    
+    // Third module
+    partialCallStack = new StackTraceElement[4];
+    partialCallStack[0] = BINDER_INSTALL;
+    partialCallStack[1] = new StackTraceElement("class1", "method1", "Class1.java", 1);
+    partialCallStack[2] = new StackTraceElement("class2", "method2", "Class2.java", 2);
+    partialCallStack[3] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$B", "configure", "Unknown Source", 200);
+    return moduleSource.createChild(new C(), partialCallStack);
+  }
+
+  private static class A extends AbstractModule {
+    @Override
+    public void configure() {
+      install(new B());
+    }
+  }
+  
+  private static class B implements Module {
+    @Override
+    public void configure(Binder binder) {
+      binder.install(new C());
+    }
+  }
+  
+  @Retention(RUNTIME)
+  @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+  @BindingAnnotation
+  @interface SampleAnnotation { }
+
+  private static class C extends AbstractModule {
+    @Override
+    public void configure() {
+      bind(String.class).annotatedWith(SampleAnnotation.class).toInstance("the value");
+    }
+  }  
+}
diff --git a/core/test/com/google/inject/spi/ElementsTest.java b/core/test/com/google/inject/spi/ElementsTest.java
new file mode 100644
index 0000000..6043fac
--- /dev/null
+++ b/core/test/com/google/inject/spi/ElementsTest.java
@@ -0,0 +1,1345 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static com.google.inject.Asserts.isIncludeStackTraceComplete;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.MembersInjector;
+import com.google.inject.Module;
+import com.google.inject.PrivateBinder;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.Scopes;
+import com.google.inject.Singleton;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.AnnotatedConstantBindingBuilder;
+import com.google.inject.binder.ConstantBindingBuilder;
+import com.google.inject.binder.ScopedBindingBuilder;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class ElementsTest extends TestCase {
+
+  // Binder fidelity tests
+
+  public void testAddMessageErrorCommand() {
+    checkModule(
+        new AbstractModule() {
+          @Override protected void configure() {
+            addError("Message %s %d %s", "A", 5, "C");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("Message A 5 C", command.getMessage());
+            assertNull(command.getCause());
+            assertContains(command.getSources().toString(),
+                ElementsTest.class.getName(),
+                getDeclaringSourcePart(ElementsTest.class));
+            assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testAddThrowableErrorCommand() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            addError(new Exception("A"));
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("A", command.getCause().getMessage());
+            assertEquals(command.getMessage(),
+                "An exception was caught and reported. Message: A");
+            assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testErrorsAddedWhenExceptionsAreThrown() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            install(new AbstractModule() {
+              protected void configure() {
+                throw new RuntimeException("Throwing RuntimeException in AbstractModule.configure().");
+              }
+            });
+
+            addError("Code after the exception still gets executed");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("Throwing RuntimeException in AbstractModule.configure().",
+                command.getCause().getMessage());
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("Code after the exception still gets executed",
+                command.getMessage());
+            return null;
+          }
+        }
+    );
+  }
+
+  private <T> T getInstance(Binding<T> binding) {
+    return binding.acceptTargetVisitor(Elements.<T>getInstanceVisitor());
+  }
+
+  public void testBindConstantAnnotations() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bindConstant().annotatedWith(SampleAnnotation.class).to("A");
+            bindConstant().annotatedWith(Names.named("Bee")).to("B");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey());
+            assertEquals("A", getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(String.class, Names.named("Bee")), command.getKey());
+            assertEquals("B", getInstance(command));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindConstantTypes() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bindConstant().annotatedWith(Names.named("String")).to("A");
+            bindConstant().annotatedWith(Names.named("int")).to(2);
+            bindConstant().annotatedWith(Names.named("long")).to(3L);
+            bindConstant().annotatedWith(Names.named("boolean")).to(false);
+            bindConstant().annotatedWith(Names.named("double")).to(5.0d);
+            bindConstant().annotatedWith(Names.named("float")).to(6.0f);
+            bindConstant().annotatedWith(Names.named("short")).to((short) 7);
+            bindConstant().annotatedWith(Names.named("char")).to('h');
+            bindConstant().annotatedWith(Names.named("byte")).to((byte) 8);
+            bindConstant().annotatedWith(Names.named("Class")).to(Iterator.class);
+            bindConstant().annotatedWith(Names.named("Enum")).to(CoinSide.TAILS);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(String.class, Names.named("String")), command.getKey());
+            assertEquals("A", getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Integer.class, Names.named("int")), command.getKey());
+            assertEquals(2, getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Long.class, Names.named("long")), command.getKey());
+            assertEquals(3L, getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Boolean.class, Names.named("boolean")), command.getKey());
+            assertEquals(false, getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Double.class, Names.named("double")), command.getKey());
+            assertEquals(5.0d, getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Float.class, Names.named("float")), command.getKey());
+            assertEquals(6.0f, getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Short.class, Names.named("short")), command.getKey());
+            assertEquals((short) 7, getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Character.class, Names.named("char")), command.getKey());
+            assertEquals('h', getInstance(command));
+            return null;
+          }
+        },
+        
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Byte.class, Names.named("byte")), command.getKey());
+            assertEquals((byte) 8, getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(Class.class, Names.named("Class")), command.getKey());
+            assertEquals(Iterator.class, getInstance(command));
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(CoinSide.class, Names.named("Enum")), command.getKey());
+            assertEquals(CoinSide.TAILS, getInstance(command));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindKeysNoAnnotations() {
+    FailingElementVisitor keyChecker = new FailingElementVisitor() {
+      @Override public <T> Void visit(Binding<T> command) {
+        assertEquals(Key.get(String.class), command.getKey());
+        return null;
+      }
+    };
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).toInstance("A");
+            bind(new TypeLiteral<String>() {}).toInstance("B");
+            bind(Key.get(String.class)).toInstance("C");
+          }
+        },
+        keyChecker,
+        keyChecker,
+        keyChecker
+    );
+  }
+
+  public void testBindKeysWithAnnotationType() {
+    FailingElementVisitor annotationChecker = new FailingElementVisitor() {
+      @Override public <T> Void visit(Binding<T> command) {
+        assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey());
+        return null;
+      }
+    };
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).annotatedWith(SampleAnnotation.class).toInstance("A");
+            bind(new TypeLiteral<String>() {}).annotatedWith(SampleAnnotation.class).toInstance("B");
+          }
+        },
+        annotationChecker,
+        annotationChecker
+    );
+  }
+
+  public void testBindKeysWithAnnotationInstance() {
+    FailingElementVisitor annotationChecker = new FailingElementVisitor() {
+      @Override public <T> Void visit(Binding<T> command) {
+        assertEquals(Key.get(String.class, Names.named("a")), command.getKey());
+        return null;
+      }
+    };
+
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).annotatedWith(Names.named("a")).toInstance("B");
+            bind(new TypeLiteral<String>() {}).annotatedWith(Names.named("a")).toInstance("C");
+          }
+        },
+        annotationChecker,
+        annotationChecker
+    );
+  }
+
+  public void testBindToProvider() {
+    final Provider<String> aProvider = new Provider<String>() {
+      public String get() {
+        return "A";
+      }
+    };
+    
+    final javax.inject.Provider<Integer> intJavaxProvider = new javax.inject.Provider<Integer>() {
+      public Integer get() {
+        return 42;
+      }
+    };
+    
+    final javax.inject.Provider<Double> doubleJavaxProvider = new javax.inject.Provider<Double>() {
+      @javax.inject.Inject String string;
+      
+      public Double get() {
+        return 42.42;
+      }
+    };
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).toProvider(aProvider);
+            bind(Integer.class).toProvider(intJavaxProvider);
+            bind(Double.class).toProvider(doubleJavaxProvider);
+            bind(List.class).toProvider(ListProvider.class);
+            bind(Collection.class).toProvider(Key.get(ListProvider.class));
+            bind(Iterable.class).toProvider(new TypeLiteral<TProvider<List>>() {});
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof ProviderInstanceBinding);
+            assertEquals(Key.get(String.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(
+                  ProviderInstanceBinding<? extends T> binding) {
+                assertSame(aProvider, binding.getUserSuppliedProvider());
+                assertSame(aProvider, binding.getProviderInstance());
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+        
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof ProviderInstanceBinding);
+            assertEquals(Key.get(Integer.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(
+                  ProviderInstanceBinding<? extends T> binding) {
+                assertSame(intJavaxProvider, binding.getUserSuppliedProvider());
+                assertEquals(42, binding.getProviderInstance().get());
+                // we don't wrap this w/ dependencies if there were none.
+                assertFalse(binding.getProviderInstance() instanceof HasDependencies);
+                return null;
+              }
+            });
+            return null;
+          }
+        },        
+        
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof ProviderInstanceBinding);
+            assertEquals(Key.get(Double.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(
+                  ProviderInstanceBinding<? extends T> binding) {
+                assertSame(doubleJavaxProvider, binding.getUserSuppliedProvider());
+                assertEquals(42.42, binding.getProviderInstance().get());
+                // we do wrap it with dependencies if there were some.
+                assertTrue(binding.getProviderInstance() instanceof HasDependencies);
+                Set<Dependency<?>> deps =
+                    ((HasDependencies) binding.getProviderInstance()).getDependencies();
+                assertEquals(1, deps.size());
+                assertEquals(String.class,
+                    deps.iterator().next().getKey().getTypeLiteral().getRawType());
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof ProviderKeyBinding);
+            assertEquals(Key.get(List.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(ProviderKeyBinding<? extends T> binding) {
+                assertEquals(Key.get(ListProvider.class), binding.getProviderKey());
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof ProviderKeyBinding);
+            assertEquals(Key.get(Collection.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(ProviderKeyBinding<? extends T> binding) {
+                assertEquals(Key.get(ListProvider.class), binding.getProviderKey());
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof ProviderKeyBinding);
+            assertEquals(Key.get(Iterable.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(ProviderKeyBinding<? extends T> binding) {
+                assertEquals(new Key<TProvider<List>>() {}, binding.getProviderKey());
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindToLinkedBinding() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(List.class).to(ArrayList.class);
+            bind(Map.class).to(new TypeLiteral<HashMap<Integer, String>>() {});
+            bind(Set.class).to(Key.get(TreeSet.class, SampleAnnotation.class));
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof LinkedKeyBinding);
+            assertEquals(Key.get(List.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(LinkedKeyBinding<? extends T> binding) {
+                assertEquals(Key.get(ArrayList.class), binding.getLinkedKey());
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof LinkedKeyBinding);
+            assertEquals(Key.get(Map.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(LinkedKeyBinding<? extends T> binding) {
+                assertEquals(Key.get(new TypeLiteral<HashMap<Integer, String>>() {}),
+                    binding.getLinkedKey());
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof LinkedKeyBinding);
+            assertEquals(Key.get(Set.class), command.getKey());
+            command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(LinkedKeyBinding<? extends T> binding) {
+                assertEquals(Key.get(TreeSet.class, SampleAnnotation.class),
+                    binding.getLinkedKey());
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindToInstance() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).toInstance("A");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertTrue(command instanceof InstanceBinding);
+            assertEquals(Key.get(String.class), command.getKey());
+            assertEquals("A", getInstance(command));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindInScopes() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class);
+            bind(List.class).to(ArrayList.class).in(Scopes.SINGLETON);
+            bind(Map.class).to(HashMap.class).in(Singleton.class);
+            bind(Set.class).to(TreeSet.class).asEagerSingleton();
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertEquals(Key.get(String.class), command.getKey());
+            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              @Override public Void visitNoScoping() {
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertEquals(Key.get(List.class), command.getKey());
+            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              @Override public Void visitScope(Scope scope) {
+                assertEquals(Scopes.SINGLETON, scope);
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertEquals(Key.get(Map.class), command.getKey());
+            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              @Override public Void visitScopeAnnotation(Class<? extends Annotation> annotation) {
+                assertEquals(Singleton.class, annotation);
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertEquals(Key.get(Set.class), command.getKey());
+            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              public Void visitEagerSingleton() {
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindToInstanceInScope() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            AnnotatedBindingBuilder<String> b = bind(String.class);
+            b.toInstance("A");
+            b.in(Singleton.class);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("Setting the scope is not permitted when binding to a single instance.",
+                command.getMessage());
+            assertNull(command.getCause());
+            assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class));
+            return null;
+          }
+        }
+      );
+  }
+
+  public void testBindToInstanceScope() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).toInstance("A");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertEquals(Key.get(String.class), binding.getKey());
+            binding.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              public Void visitEagerSingleton() {
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+      );
+  }
+
+  /*if[AOP]*/
+  public void testBindIntercepor() {
+    final Matcher<Class> classMatcher = Matchers.subclassesOf(List.class);
+    final Matcher<Object> methodMatcher = Matchers.any();
+    final org.aopalliance.intercept.MethodInterceptor methodInterceptor
+        = new org.aopalliance.intercept.MethodInterceptor() {
+      public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) {
+        return null;
+      }
+    };
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bindInterceptor(classMatcher, methodMatcher, methodInterceptor);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(InterceptorBinding command) {
+            assertSame(classMatcher, command.getClassMatcher());
+            assertSame(methodMatcher, command.getMethodMatcher());
+            assertEquals(Arrays.asList(methodInterceptor), command.getInterceptors());
+            return null;
+          }
+        }
+    );
+  }
+  /*end[AOP]*/
+
+  public void testBindScope() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bindScope(SampleAnnotation.class, Scopes.NO_SCOPE);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(ScopeBinding command) {
+            assertSame(SampleAnnotation.class, command.getAnnotationType());
+            assertSame(Scopes.NO_SCOPE, command.getScope());
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindListener() {
+    final Matcher<Object> typeMatcher = Matchers.only(TypeLiteral.get(String.class));
+    final TypeListener listener = new TypeListener() {
+      public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+        throw new UnsupportedOperationException();
+      }
+    };
+    
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bindListener(typeMatcher, listener);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(TypeListenerBinding binding) {
+            assertSame(typeMatcher, binding.getTypeMatcher());
+            assertSame(listener, binding.getListener());
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testConvertToTypes() {
+    final TypeConverter typeConverter = new TypeConverter() {
+      public Object convert(String value, TypeLiteral<?> toType) {
+        return value;
+      }
+    };
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            convertToTypes(Matchers.any(), typeConverter);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(TypeConverterBinding command) {
+            assertSame(typeConverter, command.getTypeConverter());
+            assertSame(Matchers.any(), command.getTypeMatcher());
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testGetProvider() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            Provider<String> keyGetProvider
+                = getProvider(Key.get(String.class, SampleAnnotation.class));
+            try {
+              keyGetProvider.get();
+            } catch (IllegalStateException e) {
+              assertEquals("This Provider cannot be used until the Injector has been created.",
+                  e.getMessage());
+            }
+
+            Provider<String> typeGetProvider = getProvider(String.class);
+            try {
+              typeGetProvider.get();
+            } catch (IllegalStateException e) {
+              assertEquals("This Provider cannot be used until the Injector has been created.",
+                  e.getMessage());
+            }
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(ProviderLookup<T> command) {
+            assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey());
+            assertNull(command.getDelegate());
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(ProviderLookup<T> command) {
+            assertEquals(Key.get(String.class), command.getKey());
+            assertNull(command.getDelegate());
+            return null;
+          }
+        }
+    );
+  }
+  
+  public void testElementInitialization() {
+    final AtomicReference<Provider<String>> providerFromBinder
+        = new AtomicReference<Provider<String>>();
+    final AtomicReference<MembersInjector<String>> membersInjectorFromBinder
+        = new AtomicReference<MembersInjector<String>>();
+
+    final AtomicReference<String> lastInjected = new AtomicReference<String>();
+    final MembersInjector<String> stringInjector = new MembersInjector<String>() {
+      public void injectMembers(String instance) {
+        lastInjected.set(instance);
+      }
+    };
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            providerFromBinder.set(getProvider(String.class));
+            membersInjectorFromBinder.set(getMembersInjector(String.class));
+          }
+        },
+
+        new FailingElementVisitor() {
+          public <T> Void visit(ProviderLookup<T> providerLookup) {
+            @SuppressWarnings("unchecked") // we know that T is a String here
+            ProviderLookup<String> stringLookup = (ProviderLookup<String>) providerLookup;
+            stringLookup.initializeDelegate(Providers.of("out"));
+
+            assertEquals("out", providerFromBinder.get().get());
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(MembersInjectorLookup<T> lookup) {
+            @SuppressWarnings("unchecked") // we know that T is a String here
+            MembersInjectorLookup<String> stringLookup = (MembersInjectorLookup<String>) lookup;
+            stringLookup.initializeDelegate(stringInjector);
+
+            membersInjectorFromBinder.get().injectMembers("in");
+            assertEquals("in", lastInjected.get());
+            return null;
+          }
+        });
+  }
+
+  public void testGetMembersInjector() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            MembersInjector<A<String>> typeMembersInjector
+                = getMembersInjector(new TypeLiteral<A<String>>() {});
+            try {
+              typeMembersInjector.injectMembers(new A<String>());
+            } catch (IllegalStateException e) {
+              assertEquals(
+                  "This MembersInjector cannot be used until the Injector has been created.",
+                  e.getMessage());
+            }
+
+            MembersInjector<String> classMembersInjector = getMembersInjector(String.class);
+            try {
+              classMembersInjector.injectMembers("hello");
+            } catch (IllegalStateException e) {
+              assertEquals(
+                  "This MembersInjector cannot be used until the Injector has been created.",
+                  e.getMessage());
+            }
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(MembersInjectorLookup<T> command) {
+            assertEquals(new TypeLiteral<A<String>>() {}, command.getType());
+            assertNull(command.getDelegate());
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(MembersInjectorLookup<T> command) {
+            assertEquals(TypeLiteral.get(String.class), command.getType());
+            assertNull(command.getDelegate());
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testRequestInjection() {
+    final Object firstObject = new Object();
+    final Object secondObject = new Object();
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            requestInjection(firstObject);
+            requestInjection(secondObject);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(InjectionRequest<?> command) {
+            assertEquals(firstObject, command.getInstance());
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(InjectionRequest<?> command) {
+            assertEquals(secondObject, command.getInstance());
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testRequestStaticInjection() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            requestStaticInjection(ArrayList.class);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(StaticInjectionRequest command) {
+            assertEquals(ArrayList.class, command.getType());
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testNewPrivateBinder() {
+    final Key<Collection> collection = Key.get(Collection.class, SampleAnnotation.class);
+    final Key<ArrayList> arrayList = Key.get(ArrayList.class);
+    final ImmutableSet<Key<?>> collections = ImmutableSet.<Key<?>>of(arrayList, collection);
+
+    final Key<?> a = Key.get(String.class, Names.named("a"));
+    final Key<?> b = Key.get(String.class, Names.named("b"));
+    final ImmutableSet<Key<?>> ab = ImmutableSet.of(a, b);
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            PrivateBinder one = binder().newPrivateBinder();
+            one.expose(ArrayList.class);
+            one.expose(Collection.class).annotatedWith(SampleAnnotation.class);
+            one.bind(List.class).to(ArrayList.class);
+
+            PrivateBinder two = binder().withSource("1 FooBar")
+                .newPrivateBinder().withSource("2 FooBar");
+            two.expose(String.class).annotatedWith(Names.named("a"));
+            two.expose(b);
+            two.bind(List.class).to(ArrayList.class);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(PrivateElements one) {
+            assertEquals(collections, one.getExposedKeys());
+            checkElements(one.getElements(),
+                new FailingElementVisitor() {
+                  @Override public <T> Void visit(Binding<T> binding) {
+                    assertEquals(Key.get(List.class), binding.getKey());
+                    return null;
+                  }
+                }
+            );
+            return null;
+          }
+        },
+
+        new ExternalFailureVisitor() {
+          @Override public Void visit(PrivateElements two) {
+            assertEquals(ab, two.getExposedKeys());
+            assertEquals("1 FooBar", two.getSource().toString());
+            checkElements(two.getElements(),
+                new ExternalFailureVisitor() {
+                  @Override public <T> Void visit(Binding<T> binding) {
+                    assertEquals("2 FooBar", binding.getSource().toString());
+                    assertEquals(Key.get(List.class), binding.getKey());
+                    return null;
+                  }
+                }
+            );
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindWithMultipleAnnotationsAddsError() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            AnnotatedBindingBuilder<String> abb = bind(String.class);
+            abb.annotatedWith(SampleAnnotation.class);
+            abb.annotatedWith(Names.named("A"));
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("More than one annotation is specified for this binding.",
+                command.getMessage());
+            assertNull(command.getCause());
+            assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindWithMultipleTargetsAddsError() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            AnnotatedBindingBuilder<String> abb = bind(String.class);
+            abb.toInstance("A");
+            abb.toInstance("B");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("Implementation is set more than once.", command.getMessage());
+            assertNull(command.getCause());
+            assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindWithMultipleScopesAddsError() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            ScopedBindingBuilder sbb = bind(List.class).to(ArrayList.class);
+            sbb.in(Scopes.NO_SCOPE);
+            sbb.asEagerSingleton();
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("Scope is set more than once.", command.getMessage());
+            assertNull(command.getCause());
+            assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindConstantWithMultipleAnnotationsAddsError() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            AnnotatedConstantBindingBuilder cbb = bindConstant();
+            cbb.annotatedWith(SampleAnnotation.class).to("A");
+            cbb.annotatedWith(Names.named("A"));
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message command) {
+            assertEquals("More than one annotation is specified for this binding.",
+                command.getMessage());
+            assertNull(command.getCause());
+            assertContains(command.getSource(), getDeclaringSourcePart(ElementsTest.class));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindConstantWithMultipleTargetsAddsError() {
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            ConstantBindingBuilder cbb = bindConstant().annotatedWith(SampleAnnotation.class);
+            cbb.to("A");
+            cbb.to("B");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public Void visit(Message message) {
+            assertEquals("Constant value is set more than once.", message.getMessage());
+            assertNull(message.getCause());
+            assertContains(message.getSource(), getDeclaringSourcePart(ElementsTest.class));
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindToConstructor() throws NoSuchMethodException, NoSuchFieldException {
+    final Constructor<A> aConstructor = A.class.getDeclaredConstructor();
+    final Constructor<B> bConstructor = B.class.getDeclaredConstructor(Object.class);
+    final Field field = B.class.getDeclaredField("stage");
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(A.class).toConstructor(aConstructor);
+            bind(B.class).toConstructor(bConstructor, new TypeLiteral<B<Integer>>() {})
+                .in(Singleton.class);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertEquals(new Key<A>() {}, binding.getKey());
+
+            return binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(ConstructorBinding<? extends T> constructorBinding) {
+                InjectionPoint injectionPoint = constructorBinding.getConstructor();
+                assertEquals(aConstructor, injectionPoint.getMember());
+                assertEquals(new TypeLiteral<A>() {}, injectionPoint.getDeclaringType());
+                return null;
+              }
+            });
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertEquals(new Key<B>() {}, binding.getKey());
+            binding.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              @Override public Void visitScopeAnnotation(Class<? extends Annotation> annotation) {
+                assertEquals(Singleton.class, annotation);
+                return null;
+              }
+            });
+
+            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(ConstructorBinding<? extends T> constructorBinding) {
+                assertEquals(bConstructor, constructorBinding.getConstructor().getMember());
+                assertEquals(Key.get(Integer.class),
+                    getOnlyElement(constructorBinding.getConstructor().getDependencies()).getKey());
+                assertEquals(field,
+                    getOnlyElement(constructorBinding.getInjectableMembers()).getMember());
+                assertEquals(2, constructorBinding.getDependencies().size());
+/*if[AOP]*/
+                assertEquals(ImmutableMap.of(), constructorBinding.getMethodInterceptors());
+/*end[AOP]*/
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testBindToMalformedConstructor() throws NoSuchMethodException, NoSuchFieldException {
+    final Constructor<C> constructor = C.class.getDeclaredConstructor(Integer.class);
+
+    checkModule(
+        new AbstractModule() {
+          protected void configure() {
+            bind(C.class).toConstructor(constructor);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertEquals(Key.get(C.class), binding.getKey());
+            assertTrue(binding instanceof UntargettedBinding);
+            return null;
+          }
+        },
+
+        new ExternalFailureVisitor() {
+          @Override public Void visit(Message message) {
+            assertContains(message.getMessage(),
+                C.class.getName() + ".a has more than one annotation ",
+                Named.class.getName(), SampleAnnotation.class.getName());
+            return null;
+          }
+        },
+
+        new ExternalFailureVisitor() {
+          @Override public Void visit(Message message) {
+            assertContains(message.getMessage(),
+                C.class.getName() + ".<init>() has more than one annotation ",
+                Named.class.getName(), SampleAnnotation.class.getName());
+            return null;
+          }
+        }
+    );
+  }
+
+  // Business logic tests
+
+  public void testModulesAreInstalledAtMostOnce() {
+    final AtomicInteger aConfigureCount = new AtomicInteger(0);
+    final Module a = new AbstractModule() {
+      public void configure() {
+        aConfigureCount.incrementAndGet();
+      }
+    };
+
+    Elements.getElements(a, a);
+    assertEquals(1, aConfigureCount.get());
+
+    aConfigureCount.set(0);
+    Module b = new AbstractModule() {
+      protected void configure() {
+        install(a);
+        install(a);
+      }
+    };
+
+    Elements.getElements(b);
+    assertEquals(1, aConfigureCount.get());
+  }
+
+  /**
+   * Ensures the module performs the commands consistent with {@code visitors}.
+   */
+  protected void checkModule(Module module, ElementVisitor<?>... visitors) {
+    List<Element> elements = Elements.getElements(module);
+    assertEquals(elements.size(), visitors.length);
+    checkElements(elements, visitors);
+  }
+
+  protected void checkElements(List<Element> elements, ElementVisitor<?>... visitors) {
+    for (int i = 0; i < visitors.length; i++) {
+      ElementVisitor<?> visitor = visitors[i];
+      Element element = elements.get(i);
+      if (!(element instanceof Message)) {
+          ElementSource source = (ElementSource) element.getSource();
+          assertFalse(source.getModuleClassNames().isEmpty());
+          if (isIncludeStackTraceComplete()) {
+            assertTrue(source.getStackTrace().length > 0);
+          } else {
+            assertEquals(0, source.getStackTrace().length);
+          }
+      }
+      if (!(visitor instanceof ExternalFailureVisitor)) {
+        assertContains(element.getSource().toString(), getDeclaringSourcePart(ElementsTest.class));
+      }
+      element.acceptVisitor(visitor);
+    }
+  }
+
+  private static class ListProvider implements Provider<List> {
+    public List get() {
+      return new ArrayList();
+    }
+  }
+
+  private static class TProvider<T> implements Provider<T> {
+    public T get() {
+      return null;
+    }
+  }
+
+  /**
+   * By extending this interface rather than FailingElementVisitor, the source of the error doesn't
+   * need to contain the string {@code ElementsTest.java}.
+   */
+  abstract class ExternalFailureVisitor extends FailingElementVisitor {}
+
+  @Retention(RUNTIME)
+  @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+  @BindingAnnotation
+  public @interface SampleAnnotation { }
+
+  public enum CoinSide { HEADS, TAILS }
+
+  static class A<T> {
+    @Inject Stage stage;
+  }
+
+  static class B<T> {
+    @Inject Stage stage;
+    B(T t) {}
+  }
+
+  static class C {
+    @Inject @Named("foo") @SampleAnnotation String a;
+    C(@Named("bar") @SampleAnnotation Integer b) {}
+  }
+}
diff --git a/core/test/com/google/inject/spi/FailingBindingScopingVisitor.java b/core/test/com/google/inject/spi/FailingBindingScopingVisitor.java
new file mode 100644
index 0000000..bd08c4b
--- /dev/null
+++ b/core/test/com/google/inject/spi/FailingBindingScopingVisitor.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Scope;
+
+import junit.framework.AssertionFailedError;
+
+import java.lang.annotation.Annotation;
+
+public class FailingBindingScopingVisitor implements BindingScopingVisitor<Void> {
+
+  public Void visitEagerSingleton() {
+    throw new AssertionFailedError();
+  }
+
+  public Void visitScope(Scope scope) {
+    throw new AssertionFailedError();
+  }
+
+  public Void visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
+    throw new AssertionFailedError();
+  }
+
+  public Void visitNoScoping() {
+    throw new AssertionFailedError();
+  }
+}
\ No newline at end of file
diff --git a/core/test/com/google/inject/spi/FailingElementVisitor.java b/core/test/com/google/inject/spi/FailingElementVisitor.java
new file mode 100644
index 0000000..d40d084
--- /dev/null
+++ b/core/test/com/google/inject/spi/FailingElementVisitor.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import junit.framework.AssertionFailedError;
+
+class FailingElementVisitor extends DefaultElementVisitor<Void> {
+  @Override protected Void visitOther(Element element) {
+    throw new AssertionFailedError();
+  }
+}
diff --git a/core/test/com/google/inject/spi/FailingTargetVisitor.java b/core/test/com/google/inject/spi/FailingTargetVisitor.java
new file mode 100644
index 0000000..68d5f7e
--- /dev/null
+++ b/core/test/com/google/inject/spi/FailingTargetVisitor.java
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.inject.Binding;
+
+import junit.framework.AssertionFailedError;
+
+public class FailingTargetVisitor<T> extends DefaultBindingTargetVisitor<T, Void> {
+  @Override protected Void visitOther(Binding<? extends T> binding) {
+    throw new AssertionFailedError();
+  }
+}
diff --git a/core/test/com/google/inject/spi/HasDependenciesTest.java b/core/test/com/google/inject/spi/HasDependenciesTest.java
new file mode 100644
index 0000000..670f2f4
--- /dev/null
+++ b/core/test/com/google/inject/spi/HasDependenciesTest.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+
+import junit.framework.TestCase;
+
+import java.util.Set;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class HasDependenciesTest extends TestCase {
+
+  /**
+   * When an instance implements HasDependencies, the injected dependencies aren't used.
+   */
+  public void testInstanceWithDependencies() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(A.class).toInstance(new AWithDependencies());
+      }
+    });
+
+    InstanceBinding<?> binding = (InstanceBinding<?>) injector.getBinding(A.class);
+    assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Integer.class))),
+        binding.getDependencies());
+  }
+
+  public void testInstanceWithoutDependencies() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(A.class).toInstance(new A());
+      }
+    });
+
+    InstanceBinding<?> binding = (InstanceBinding<?>) injector.getBinding(A.class);
+    Dependency<?> onlyDependency = Iterables.getOnlyElement(binding.getDependencies());
+    assertEquals(Key.get(String.class), onlyDependency.getKey());
+  }
+
+  public void testProvider() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(A.class).toProvider(new ProviderOfA());
+      }
+    });
+
+    ProviderInstanceBinding<?> binding = (ProviderInstanceBinding<?>) injector.getBinding(A.class);
+    Dependency<?> onlyDependency = Iterables.getOnlyElement(binding.getDependencies());
+    assertEquals(Key.get(String.class), onlyDependency.getKey());
+  }
+
+  static class A {
+    @Inject void injectUnusedDependencies(String unused) {}
+  }
+
+  static class ProviderOfA implements Provider<A> {
+    @Inject void injectUnusedDependencies(String unused) {}
+
+    public A get() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  static class AWithDependencies extends A implements HasDependencies {
+    public Set<Dependency<?>> getDependencies() {
+      return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Integer.class)));
+    }
+  }
+
+  static class ProviderOfAWithDependencies
+      extends ProviderOfA implements ProviderWithDependencies<A> {
+    public Set<Dependency<?>> getDependencies() {
+      return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Integer.class)));
+    }
+  }
+}
diff --git a/core/test/com/google/inject/spi/InjectionPointTest.java b/core/test/com/google/inject/spi/InjectionPointTest.java
new file mode 100644
index 0000000..2ba4f5b
--- /dev/null
+++ b/core/test/com/google/inject/spi/InjectionPointTest.java
@@ -0,0 +1,366 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.assertEqualsBothWays;
+import static com.google.inject.Asserts.assertNotSerializable;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.ErrorsException;
+import com.google.inject.name.Named;
+import com.google.inject.spi.InjectionPoint.Signature;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class InjectionPointTest extends TestCase {
+
+  public @Inject @Named("a") String foo;
+  public @Inject void bar(@Named("b") String param) {}
+
+  public static class Constructable {
+    @Inject public Constructable(@Named("c") String param) {}
+  }
+
+  public void testFieldInjectionPoint() throws NoSuchFieldException, IOException, ErrorsException {
+    TypeLiteral<?> typeLiteral = TypeLiteral.get(getClass());
+    Field fooField = getClass().getField("foo");
+
+    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, fooField, false);
+    assertSame(fooField, injectionPoint.getMember());
+    assertFalse(injectionPoint.isOptional());
+    assertEquals(getClass().getName() + ".foo", injectionPoint.toString());
+    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, fooField, false));
+    assertNotSerializable(injectionPoint);
+
+    Dependency<?> dependency = getOnlyElement(injectionPoint.getDependencies());
+    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=a)]@"
+        + getClass().getName() + ".foo", dependency.toString());
+    assertEquals(fooField, dependency.getInjectionPoint().getMember());
+    assertEquals(-1, dependency.getParameterIndex());
+    assertEquals(Key.get(String.class, named("a")), dependency.getKey());
+    assertFalse(dependency.isNullable());
+    assertNotSerializable(dependency);
+    assertEqualsBothWays(dependency,
+        getOnlyElement(new InjectionPoint(typeLiteral, fooField, false).getDependencies()));
+  }
+
+  public void testMethodInjectionPoint() throws Exception {
+    TypeLiteral<?> typeLiteral = TypeLiteral.get(getClass());
+
+    Method barMethod = getClass().getMethod("bar", String.class);
+    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, barMethod, false);
+    assertSame(barMethod, injectionPoint.getMember());
+    assertFalse(injectionPoint.isOptional());
+    assertEquals(getClass().getName() + ".bar()", injectionPoint.toString());
+    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, barMethod, false));
+    assertNotSerializable(injectionPoint);
+
+    Dependency<?> dependency = getOnlyElement(injectionPoint.getDependencies());
+    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=b)]@"
+        + getClass().getName() + ".bar()[0]", dependency.toString());
+    assertEquals(barMethod, dependency.getInjectionPoint().getMember());
+    assertEquals(0, dependency.getParameterIndex());
+    assertEquals(Key.get(String.class, named("b")), dependency.getKey());
+    assertFalse(dependency.isNullable());
+    assertNotSerializable(dependency);
+    assertEqualsBothWays(dependency,
+        getOnlyElement(new InjectionPoint(typeLiteral, barMethod, false).getDependencies()));
+  }
+
+  public void testConstructorInjectionPoint() throws NoSuchMethodException, IOException,
+      ErrorsException {
+    TypeLiteral<?> typeLiteral = TypeLiteral.get(Constructable.class);
+
+    Constructor<?> constructor = Constructable.class.getConstructor(String.class);
+    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, constructor);
+    assertSame(constructor, injectionPoint.getMember());
+    assertFalse(injectionPoint.isOptional());
+    assertEquals(Constructable.class.getName() + ".<init>()", injectionPoint.toString());
+    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, constructor));
+    assertNotSerializable(injectionPoint);
+
+    Dependency<?> dependency = getOnlyElement(injectionPoint.getDependencies());
+    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=c)]@"
+        + Constructable.class.getName() + ".<init>()[0]", dependency.toString());
+    assertEquals(constructor, dependency.getInjectionPoint().getMember());
+    assertEquals(0, dependency.getParameterIndex());
+    assertEquals(Key.get(String.class, named("c")), dependency.getKey());
+    assertFalse(dependency.isNullable());
+    assertNotSerializable(dependency);
+    assertEqualsBothWays(dependency,
+        getOnlyElement(new InjectionPoint(typeLiteral, constructor).getDependencies()));
+  }
+
+  public void testUnattachedDependency() throws IOException {
+    Dependency<String> dependency = Dependency.get(Key.get(String.class, named("d")));
+    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=d)]",
+        dependency.toString());
+    assertNull(dependency.getInjectionPoint());
+    assertEquals(-1, dependency.getParameterIndex());
+    assertEquals(Key.get(String.class, named("d")), dependency.getKey());
+    assertTrue(dependency.isNullable());
+    assertNotSerializable(dependency);
+    assertEqualsBothWays(dependency, Dependency.get(Key.get(String.class, named("d"))));
+  }
+
+  public void testForConstructor() throws NoSuchMethodException {
+    Constructor<HashSet> constructor = HashSet.class.getConstructor();
+    TypeLiteral<HashSet<String>> hashSet = new TypeLiteral<HashSet<String>>() {};
+
+    InjectionPoint injectionPoint = InjectionPoint.forConstructor(constructor, hashSet);
+    assertSame(constructor, injectionPoint.getMember());
+    assertEquals(ImmutableList.<Dependency>of(), injectionPoint.getDependencies());
+    assertFalse(injectionPoint.isOptional());
+
+    try {
+      InjectionPoint.forConstructor(constructor, new TypeLiteral<LinkedHashSet<String>>() {});
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), "java.util.LinkedHashSet<java.lang.String>",
+          " does not define java.util.HashSet.<init>()",
+          "  while locating java.util.LinkedHashSet<java.lang.String>");
+    }
+
+    try {
+      InjectionPoint.forConstructor((Constructor) constructor, new TypeLiteral<Set<String>>() {});
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), "java.util.Set<java.lang.String>",
+          " does not define java.util.HashSet.<init>()",
+          "  while locating java.util.Set<java.lang.String>");
+    }
+  }
+
+  public void testForConstructorOf() {
+    InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Constructable.class);
+    assertEquals(Constructable.class.getName() + ".<init>()", injectionPoint.toString());
+  }
+
+  public void testAddForInstanceMethodsAndFields() throws Exception {
+    Method instanceMethod = HasInjections.class.getMethod("instanceMethod", String.class);
+    Field instanceField = HasInjections.class.getField("instanceField");
+
+    TypeLiteral<HasInjections> type = TypeLiteral.get(HasInjections.class);
+    assertEquals(ImmutableSet.of(
+        new InjectionPoint(type, instanceMethod, false),
+        new InjectionPoint(type, instanceField, false)),
+        InjectionPoint.forInstanceMethodsAndFields(HasInjections.class));
+  }
+
+  public void testAddForStaticMethodsAndFields() throws Exception {
+    Method staticMethod = HasInjections.class.getMethod("staticMethod", String.class);
+    Field staticField = HasInjections.class.getField("staticField");
+
+    Set<InjectionPoint> injectionPoints = InjectionPoint.forStaticMethodsAndFields(
+        HasInjections.class);
+    assertEquals(ImmutableSet.of(
+        new InjectionPoint(TypeLiteral.get(HasInjections.class), staticMethod, false),
+        new InjectionPoint(TypeLiteral.get(HasInjections.class), staticField, false)),
+        injectionPoints);
+  }
+
+  static class HasInjections {
+    @Inject public static void staticMethod(@Named("a") String a) {}
+    @Inject @Named("c") public static String staticField;
+    @Inject public void instanceMethod(@Named("d") String d) {}
+    @Inject @Named("f") public String instanceField;
+  }
+
+  public void testAddForParameterizedInjections() {
+    TypeLiteral<?> type = new TypeLiteral<ParameterizedInjections<String>>() {};
+
+    InjectionPoint constructor = InjectionPoint.forConstructorOf(type);
+    assertEquals(new Key<Map<String, String>>() {},
+        getOnlyElement(constructor.getDependencies()).getKey());
+
+    InjectionPoint field = getOnlyElement(InjectionPoint.forInstanceMethodsAndFields(type));
+    assertEquals(new Key<Set<String>>() {}, getOnlyElement(field.getDependencies()).getKey());
+  }
+
+  static class ParameterizedInjections<T> {
+    @Inject Set<T> setOfTees;
+    @Inject public ParameterizedInjections(Map<T, T> map) {}
+  }
+
+  public void testSignature() throws Exception {
+    Signature fooA = new Signature(Foo.class.getDeclaredMethod(
+        "a", String.class, int.class));
+    Signature fooB = new Signature(Foo.class.getDeclaredMethod("b"));
+    Signature barA = new Signature(Bar.class.getDeclaredMethod(
+        "a", String.class, int.class));
+    Signature barB = new Signature(Bar.class.getDeclaredMethod("b"));
+
+    assertEquals(fooA.hashCode(), barA.hashCode());
+    assertEquals(fooB.hashCode(), barB.hashCode());
+    assertEquals(fooA, barA);
+    assertEquals(fooB, barB);
+  }
+
+  static class Foo {
+    void a(String s, int i) {}
+    int b() {
+      return 0;
+    }
+  }
+  static class Bar {
+    public void a(String s, int i) {}
+    void b() {}
+  }
+  
+  public void testOverrideBehavior() {
+    Set<InjectionPoint> points;
+
+    points = InjectionPoint.forInstanceMethodsAndFields(Super.class);
+    assertEquals(points.toString(), 6, points.size());
+    assertPoints(points, Super.class, "atInject", "gInject", "privateAtAndPublicG",
+        "privateGAndPublicAt", "atFirstThenG", "gFirstThenAt");
+
+    points = InjectionPoint.forInstanceMethodsAndFields(Sub.class);
+    assertEquals(points.toString(), 7, points.size());
+    // Superclass will always have is private members injected,
+    // and 'gInject' was last @Injected in Super, so that remains the owner
+    assertPoints(points, Super.class, "privateAtAndPublicG", "privateGAndPublicAt", "gInject");
+    // Subclass also has the "private" methods, but they do not override
+    // the superclass' methods, and it now owns the inject2 methods.
+    assertPoints(points, Sub.class, "privateAtAndPublicG", "privateGAndPublicAt",
+        "atFirstThenG", "gFirstThenAt");
+    
+    points = InjectionPoint.forInstanceMethodsAndFields(SubSub.class);
+    assertEquals(points.toString(), 6, points.size());
+    // Superclass still has all the injection points it did before..
+    assertPoints(points, Super.class, "privateAtAndPublicG", "privateGAndPublicAt", "gInject");
+    // Subclass is missing the privateGAndPublicAt because it first became public with
+    // javax.inject.Inject and was overrode without an annotation, which means it
+    // disappears.  (It was guice @Inject in Super, but it was private there, so it doesn't
+    // effect the annotations of the subclasses.)
+    assertPoints(points, Sub.class, "privateAtAndPublicG", "atFirstThenG", "gFirstThenAt");    
+  }
+  
+  /**
+   * This test serves two purposes:
+   *   1) It makes sure that the bridge methods javax generates don't stop
+   *   us from injecting superclass methods in the case of javax.inject.Inject.
+   *   This would happen prior to java8 (where javac didn't copy annotations
+   *   from the superclass into the subclass method when it generated the
+   *   bridge methods).
+   *   
+   *   2) It makes sure that the methods we're going to inject have the correct
+   *   generic types.  Java8 copies the annotations from super to subclasses,
+   *   but it doesn't copy the generic type information.  Guice would naively
+   *   consider the subclass an injectable method and eject the superclass
+   *   from the 'overrideIndex', leaving only a class with improper generic types.
+   */
+  public void testSyntheticBridgeMethodsInSubclasses() {
+    Set<InjectionPoint> points;
+    
+    points = InjectionPoint.forInstanceMethodsAndFields(RestrictedSuper.class);
+    assertPointDependencies(points, new TypeLiteral<Provider<String>>() {});
+    assertEquals(points.toString(), 2, points.size());
+    assertPoints(points, RestrictedSuper.class, "jInject", "gInject");
+    
+    points = InjectionPoint.forInstanceMethodsAndFields(ExposedSub.class);
+    assertPointDependencies(points, new TypeLiteral<Provider<String>>() {});
+    assertEquals(points.toString(), 2, points.size());
+    assertPoints(points, RestrictedSuper.class, "jInject", "gInject");
+  }
+  
+  private void assertPoints(Iterable<InjectionPoint> points, Class<?> clazz,
+      String... methodNames) {
+    Set<String> methods = new HashSet<String>();
+    for (InjectionPoint point : points) {
+      if (point.getDeclaringType().getRawType() == clazz) {
+        methods.add(point.getMember().getName());
+      }
+    }
+    assertEquals(points.toString(), ImmutableSet.copyOf(methodNames), methods);
+  }
+  
+  /** Asserts that each injection point has the specified dependencies, in the given order. */
+  private void assertPointDependencies(Iterable<InjectionPoint> points,
+      TypeLiteral<?>... literals) {
+    for (InjectionPoint point : points) {
+      assertEquals(literals.length, point.getDependencies().size());
+      for (Dependency<?> dep : point.getDependencies()) {
+        assertEquals(literals[dep.getParameterIndex()], dep.getKey().getTypeLiteral());
+      }
+    }
+  }
+  
+  static class Super {
+    @javax.inject.Inject public void atInject() {}
+    @com.google.inject.Inject public void gInject() {}
+
+    @javax.inject.Inject private void privateAtAndPublicG() {}
+    @com.google.inject.Inject private void privateGAndPublicAt() {}
+
+    @javax.inject.Inject public void atFirstThenG() {}
+    @com.google.inject.Inject public void gFirstThenAt() {}
+  }
+  
+  static class Sub extends Super {
+    public void atInject() {}
+    public void gInject() {}
+    
+    @com.google.inject.Inject public void privateAtAndPublicG() {}
+    @javax.inject.Inject public void privateGAndPublicAt() {}
+    
+    @com.google.inject.Inject
+    @Override 
+    public void atFirstThenG() {}
+    
+    @javax.inject.Inject
+    @Override 
+    public void gFirstThenAt() {}
+  }
+  
+  static class SubSub extends Sub {
+    @Override public void privateAtAndPublicG() {}
+    @Override public void privateGAndPublicAt() {}
+    
+    @Override public void atFirstThenG() {}
+    @Override public void gFirstThenAt() {}
+  }
+  
+  static class RestrictedSuper {
+    @com.google.inject.Inject public void gInject(Provider<String> p) {}
+    @javax.inject.Inject public void jInject(Provider<String> p) {}
+  }
+  
+  public static class ExposedSub extends RestrictedSuper {
+    // The subclass may generate bridge/synthetic methods to increase the visibility
+    // of the superclass methods, since the superclass was package-private but this is public.
+  }
+}
diff --git a/core/test/com/google/inject/spi/InjectorSpiTest.java b/core/test/com/google/inject/spi/InjectorSpiTest.java
new file mode 100644
index 0000000..a973fe9
--- /dev/null
+++ b/core/test/com/google/inject/spi/InjectorSpiTest.java
@@ -0,0 +1,74 @@
+package com.google.inject.spi;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+
+import junit.framework.TestCase;
+
+import java.util.Map;
+
+/**
+ * @author sberlin@gmail.com (Sam Berlin)
+ */
+public class InjectorSpiTest extends TestCase {
+
+  public void testExistingBinding() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Foo.class);
+        bind(Baz.class);
+      }
+    });
+    // Sanity check -- ensure we return the proper binding for all existing bindings.
+    for(Map.Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
+      assertSame(entry.getValue(), injector.getExistingBinding(entry.getKey()));
+    }
+    
+    // Now run through specifics...
+    Binding<?> binding;
+    
+    // 1) non-Provider Foo.class
+    binding = injector.getExistingBinding(Key.get(Foo.class));
+    assertNotNull(binding);
+    assertEquals(Foo.class, binding.getKey().getTypeLiteral().getRawType());
+    
+    // 2) Provider<Foo> class (should already exist, because Baz @Injects it).
+    // the assertTrue is a bit stricter than necessary, but makes sure this works for pre-existing Provider bindings
+    assertTrue(injector.getAllBindings().containsKey(Key.get(new TypeLiteral<Provider<Foo>>() {})));
+    binding = injector.getExistingBinding(Key.get(new TypeLiteral<Provider<Foo>>() {}));
+    assertNotNull(binding);
+    assertEquals(Provider.class, binding.getKey().getTypeLiteral().getRawType());
+    assertEquals(Foo.class, ((Provider)binding.getProvider().get()).get().getClass());
+    
+    // 3) non-Provider Baz.class
+    binding = injector.getExistingBinding(Key.get(Baz.class));
+    assertNotNull(binding);
+    assertEquals(Baz.class, binding.getKey().getTypeLiteral().getRawType());
+    
+    // 4) Provider<Baz> class (should not already exist, because nothing used it yet).
+    // the assertFalse is a bit stricter than necessary, but makes sure this works for non-pre-existing Provider bindings
+    assertFalse(injector.getAllBindings().containsKey(Key.get(new TypeLiteral<Provider<Baz>>() {})));    
+    binding = injector.getExistingBinding(Key.get(new TypeLiteral<Provider<Baz>>() {}));
+    assertNotNull(binding);
+    assertEquals(Provider.class, binding.getKey().getTypeLiteral().getRawType());
+    assertEquals(Baz.class, ((Provider)binding.getProvider().get()).get().getClass());
+    
+    // 5) non-Provider Bar, doesn't exist.
+    assertNull(injector.getExistingBinding(Key.get(Bar.class)));
+    
+    // 6) Provider Bar, doesn't exist.
+    assertNull(injector.getExistingBinding(Key.get(new TypeLiteral<Provider<Bar>>() {})));
+  }
+  
+  private static class Foo {}
+  private static class Bar {}
+  private static class Baz { @SuppressWarnings("unused") @Inject Provider<Foo> fooP; }
+  
+}
diff --git a/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java b/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java
new file mode 100644
index 0000000..6c797b1
--- /dev/null
+++ b/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java
@@ -0,0 +1,394 @@
+/**
+ * Copyright (C) 2015 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.inject.spi;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.name.Names.named;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.CreationException;
+import com.google.inject.Exposed;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.PrivateModule;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.Set;
+
+/** Tests for {@link ModuleAnnotatedMethodScanner} usage. */
+public class ModuleAnnotatedMethodScannerTest extends TestCase {
+
+  public void testScanning() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {}
+
+      @TestProvides @Named("foo") String foo() {
+        return "foo";
+      }
+
+      @TestProvides @Named("foo2") String foo2() {
+        return "foo2";
+      }
+    };
+    Injector injector = Guice.createInjector(module, NamedMunger.module());
+
+    // assert no bindings named "foo" or "foo2" exist -- they were munged.
+    assertMungedBinding(injector, String.class, "foo", "foo");
+    assertMungedBinding(injector, String.class, "foo2", "foo2");
+
+    Binding<String> fooBinding = injector.getBinding(Key.get(String.class, named("foo-munged")));
+    Binding<String> foo2Binding = injector.getBinding(Key.get(String.class, named("foo2-munged")));
+    // Validate the provider has a sane toString
+    assertEquals(methodName(TestProvides.class, "foo", module),
+        fooBinding.getProvider().toString());
+    assertEquals(methodName(TestProvides.class, "foo2", module),
+        foo2Binding.getProvider().toString());
+  }
+
+  public void testSkipSources() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        binder().skipSources(getClass()).install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @TestProvides @Named("foo") String foo() { return "foo"; }
+        });
+      }
+    };
+    Injector injector = Guice.createInjector(module, NamedMunger.module());
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+  
+  public void testWithSource() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        binder().withSource("source").install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @TestProvides @Named("foo") String foo() { return "foo"; }
+        });
+      }
+    };
+    Injector injector = Guice.createInjector(module, NamedMunger.module());
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testMoreThanOneClaimedAnnotationFails() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {}
+
+      @TestProvides @TestProvides2 String foo() {
+        return "foo";
+      }
+    };
+    try {
+      Guice.createInjector(module, NamedMunger.module());
+      fail();
+    } catch(CreationException expected) {
+      assertEquals(1, expected.getErrorMessages().size());
+      assertContains(expected.getMessage(),
+          "More than one annotation claimed by NamedMunger on method "
+              + module.getClass().getName() + ".foo(). Methods can only have "
+              + "one annotation claimed per scanner.");
+    }
+  }
+
+  private String methodName(Class<? extends Annotation> annotation, String method, Object container)
+      throws Exception {
+    return "@" + annotation.getName() + " "
+        + StackTraceElements.forMember(container.getClass().getDeclaredMethod(method));
+  }
+
+  @Documented @Target(METHOD) @Retention(RUNTIME)
+  private @interface TestProvides {}
+
+  @Documented @Target(METHOD) @Retention(RUNTIME)
+  private @interface TestProvides2 {}
+
+  private static class NamedMunger extends ModuleAnnotatedMethodScanner {
+    static Module module() {
+      return new AbstractModule() {
+        @Override protected void configure() {
+          binder().scanModulesForAnnotatedMethods(new NamedMunger());
+        }
+      };
+    }
+
+    @Override
+    public String toString() {
+      return "NamedMunger";
+    }
+
+    @Override
+    public Set<? extends Class<? extends Annotation>> annotationClasses() {
+      return ImmutableSet.of(TestProvides.class, TestProvides2.class);
+    }
+
+    @Override
+    public <T> Key<T> prepareMethod(Binder binder, Annotation annotation, Key<T> key,
+        InjectionPoint injectionPoint) {
+      return Key.get(key.getTypeLiteral(),
+          Names.named(((Named) key.getAnnotation()).value() + "-munged"));
+    }
+  }
+
+  private void assertMungedBinding(Injector injector, Class<?> clazz, String originalName,
+      Object expectedValue) {
+    assertNull(injector.getExistingBinding(Key.get(clazz, named(originalName))));
+    Binding<?> fooBinding = injector.getBinding(Key.get(clazz, named(originalName + "-munged")));
+    assertEquals(expectedValue, fooBinding.getProvider().get());
+  }
+
+  public void testFailingScanner() {
+    try {
+      Guice.createInjector(new SomeModule(), FailingScanner.module());
+      fail();
+    } catch (CreationException expected) {
+      Message m = Iterables.getOnlyElement(expected.getErrorMessages());
+      assertEquals(
+          "An exception was caught and reported. Message: Failing in the scanner.",
+          m.getMessage());
+      assertEquals(IllegalStateException.class, m.getCause().getClass());
+      ElementSource source = (ElementSource) Iterables.getOnlyElement(m.getSources());
+      assertEquals(SomeModule.class.getName(),
+          Iterables.getOnlyElement(source.getModuleClassNames()));
+      assertEquals(String.class.getName() + " " + SomeModule.class.getName() + ".aString()",
+          source.toString());
+    }
+  }
+
+  public static class FailingScanner extends ModuleAnnotatedMethodScanner {
+    static Module module() {
+      return new AbstractModule() {
+        @Override protected void configure() {
+          binder().scanModulesForAnnotatedMethods(new FailingScanner());
+        }
+      };
+    }
+
+    @Override public Set<? extends Class<? extends Annotation>> annotationClasses() {
+      return ImmutableSet.of(TestProvides.class);
+    }
+
+    @Override public <T> Key<T> prepareMethod(
+        Binder binder, Annotation rawAnnotation, Key<T> key, InjectionPoint injectionPoint) {
+      throw new IllegalStateException("Failing in the scanner.");
+    }
+  }
+
+  static class SomeModule extends AbstractModule {
+    @TestProvides String aString() {
+      return "Foo";
+    }
+
+    @Override protected void configure() {}
+  }
+
+  public void testChildInjectorInheritsScanner() {
+    Injector parent = Guice.createInjector(NamedMunger.module());
+    Injector child = parent.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {}
+
+      @TestProvides @Named("foo") String foo() {
+        return "foo";
+      }
+    });
+    assertMungedBinding(child, String.class, "foo", "foo");
+  }
+
+  public void testChildInjectorScannersDontImpactSiblings() {
+    Module module = new AbstractModule() {
+      @Override
+      protected void configure() {}
+
+      @TestProvides @Named("foo") String foo() {
+        return "foo";
+      }
+    };
+    Injector parent = Guice.createInjector();
+    Injector child = parent.createChildInjector(NamedMunger.module(), module);
+    assertMungedBinding(child, String.class, "foo", "foo");
+
+    // no foo nor foo-munged in sibling, since scanner never saw it.
+    Injector sibling = parent.createChildInjector(module);
+    assertNull(sibling.getExistingBinding(Key.get(String.class, named("foo"))));
+    assertNull(sibling.getExistingBinding(Key.get(String.class, named("foo-munged"))));
+  }
+
+  public void testPrivateModuleInheritScanner_usingPrivateModule() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new PrivateModule() {
+      @Override protected void configure() {}
+
+      @Exposed @TestProvides @Named("foo") String foo() {
+        return "foo";
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModule_skipSourcesWithinPrivateModule() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new PrivateModule() {
+      @Override protected void configure() {
+        binder().skipSources(getClass()).install(new AbstractModule() {
+          @Override protected void configure() {}
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModule_skipSourcesForPrivateModule() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() {
+      @Override protected void configure() {
+        binder().skipSources(getClass()).install(new PrivateModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }});
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModuleInheritScanner_usingPrivateBinder() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() {
+      @Override protected void configure() {
+        binder().newPrivateBinder().install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModuleInheritScanner_skipSourcesFromPrivateBinder() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() {
+      @Override protected void configure() {
+        binder().newPrivateBinder().skipSources(getClass()).install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModuleInheritScanner_skipSourcesFromPrivateBinder2() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() {
+      @Override protected void configure() {
+        binder().skipSources(getClass()).newPrivateBinder().install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModuleScannersDontImpactSiblings_usingPrivateModule() {
+    Injector injector = Guice.createInjector(new PrivateModule() {
+      @Override protected void configure() {
+        install(NamedMunger.module());
+      }
+
+      @Exposed @TestProvides @Named("foo") String foo() {
+        return "foo";
+      }
+    }, new PrivateModule() {
+      @Override protected void configure() {}
+
+      // ignored! (because the scanner doesn't run over this module)
+      @Exposed @TestProvides @Named("foo") String foo() {
+        return "foo";
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModuleScannersDontImpactSiblings_usingPrivateBinder() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        binder().newPrivateBinder().install(new AbstractModule() {
+          @Override protected void configure() {
+            install(NamedMunger.module());
+          }
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    }, new AbstractModule() {
+      @Override protected void configure() {
+        binder().newPrivateBinder().install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          // ignored! (because the scanner doesn't run over this module)
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }});
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModuleWithinPrivateModule() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new PrivateModule() {
+      @Override protected void configure() {
+        expose(Key.get(String.class, named("foo-munged")));
+        install(new PrivateModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+}
diff --git a/core/test/com/google/inject/spi/ModuleRewriterTest.java b/core/test/com/google/inject/spi/ModuleRewriterTest.java
new file mode 100644
index 0000000..06581da
--- /dev/null
+++ b/core/test/com/google/inject/spi/ModuleRewriterTest.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import com.google.common.collect.Lists;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class ModuleRewriterTest extends TestCase {
+
+  public void testRewriteBindings() {
+    // create a module the binds String.class and CharSequence.class
+    Module module = new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toInstance("Pizza");
+        bind(CharSequence.class).toInstance("Wine");
+      }
+    };
+
+    // record the elements from that module
+    List<Element> elements = Elements.getElements(module);
+
+    // create a rewriter that rewrites the binding to 'Wine' with a binding to 'Beer'
+    List<Element> rewritten = Lists.newArrayList();
+    for (Element element : elements) {
+      element = element.acceptVisitor(new DefaultElementVisitor<Element>() {
+        @Override public <T> Element visit(Binding<T> binding) {
+          T target = binding.acceptTargetVisitor(Elements.<T>getInstanceVisitor());
+          if ("Wine".equals(target)) {
+            return null;
+          }
+          else {
+            return binding;
+          }
+        }
+      });
+      if (element != null) {
+        rewritten.add(element);
+      }
+    }
+
+    // create a module from the original list of elements and the rewriter
+    Module rewrittenModule = Elements.getModule(rewritten);
+
+    // the wine binding is dropped
+    Injector injector = Guice.createInjector(rewrittenModule);
+    try {
+      injector.getInstance(CharSequence.class);
+      fail();
+    } catch (ConfigurationException expected) {
+    }
+  }
+
+  public void testGetProviderAvailableAtInjectMembersTime() {
+    Module module = new AbstractModule() {
+      public void configure() {
+        final Provider<String> stringProvider = getProvider(String.class);
+
+        bind(String.class).annotatedWith(Names.named("2")).toProvider(new Provider<String>() {
+          private String value;
+
+          @Inject void initialize() {
+            value = stringProvider.get();
+          }
+
+          public String get() {
+            return value;
+          }
+        });
+
+        bind(String.class).toInstance("A");
+      }
+    };
+
+    // the module works fine normally
+    Injector injector = Guice.createInjector(module);
+    assertEquals("A", injector.getInstance(Key.get(String.class, Names.named("2"))));
+
+    // and it should also work fine if we rewrite it
+    List<Element> elements = Elements.getElements(module);
+    Module replayed = Elements.getModule(elements);
+    Injector replayedInjector = Guice.createInjector(replayed);
+    assertEquals("A", replayedInjector.getInstance(Key.get(String.class, Names.named("2"))));
+  }
+}
diff --git a/core/test/com/google/inject/spi/ModuleSourceTest.java b/core/test/com/google/inject/spi/ModuleSourceTest.java
new file mode 100644
index 0000000..b72d976
--- /dev/null
+++ b/core/test/com/google/inject/spi/ModuleSourceTest.java
@@ -0,0 +1,125 @@
+package com.google.inject.spi;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Module;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link ModuleSource}.
+ */
+public class ModuleSourceTest extends TestCase {
+
+  private static final StackTraceElement BINDER_INSTALL = 
+      new StackTraceElement("com.google.inject.spi.Elements$RecordingBinder", "install", 
+          "Unknown Source", 235 /* line number*/);
+  
+  public void testOneModule() {
+    ModuleSource moduleSource = createWithSizeOne();
+    checkSizeOne(moduleSource);    
+  }
+  
+  public void testTwoModules() {
+    ModuleSource moduleSource = createWithSizeTwo();
+    checkSizeTwo(moduleSource);
+    moduleSource = moduleSource.getParent();
+    checkSizeOne(moduleSource);
+  }
+  
+  public void testThreeModules() {
+    ModuleSource moduleSource = createWithSizeThree();
+    checkSizeThree(moduleSource);
+    moduleSource = moduleSource.getParent();
+    checkSizeTwo(moduleSource);
+    moduleSource = moduleSource.getParent();
+    checkSizeOne(moduleSource);
+  }
+
+  private void checkSizeOne(ModuleSource moduleSource) {
+    assertEquals(1, moduleSource.size());
+    assertEquals(1, moduleSource.getStackTraceSize());
+    // Check call stack
+    StackTraceElement[] callStack = moduleSource.getStackTrace();
+    assertEquals(BINDER_INSTALL, callStack[0]);    
+  }
+  
+  private void checkSizeTwo(ModuleSource moduleSource) {
+    assertEquals(2, moduleSource.size());
+    assertEquals(3, moduleSource.getStackTraceSize());
+    // Check call stack
+    StackTraceElement[] callStack = moduleSource.getStackTrace();
+    assertEquals(BINDER_INSTALL, callStack[0]);    
+    assertEquals(
+        new StackTraceElement(
+            "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100),
+        callStack[1]);
+    assertEquals(BINDER_INSTALL, callStack[2]);    
+  }
+  
+  private void checkSizeThree(ModuleSource moduleSource) {
+    assertEquals(3, moduleSource.size());
+    assertEquals(7, moduleSource.getStackTraceSize());
+    // Check call stack
+    StackTraceElement[] callStack = moduleSource.getStackTrace();
+    assertEquals(BINDER_INSTALL, callStack[0]);    
+    assertEquals(new StackTraceElement("class1", "method1", "Unknown Source", 1), callStack[1]);
+    assertEquals(new StackTraceElement("class2", "method2", "Unknown Source", 2), callStack[2]);   
+    assertEquals(
+        new StackTraceElement(
+            "com.google.inject.spi.moduleSourceTest$B", "configure", "Unknown Source", 200),
+            callStack[3]); 
+    assertEquals(BINDER_INSTALL, callStack[4]);    
+
+    assertEquals(
+        new StackTraceElement(
+            "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100),
+        callStack[5]);
+    assertEquals(BINDER_INSTALL, callStack[6]);    
+  }
+  
+  private ModuleSource createWithSizeOne() {
+    StackTraceElement[] partialCallStack = new StackTraceElement[1];
+    partialCallStack[0] = BINDER_INSTALL;    
+    return new ModuleSource(new A(), partialCallStack);
+  }
+  
+  private ModuleSource createWithSizeTwo() {
+    ModuleSource moduleSource = createWithSizeOne();
+    StackTraceElement[] partialCallStack = new StackTraceElement[2];
+    partialCallStack[0] = BINDER_INSTALL;
+    partialCallStack[1] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$A", "configure", "moduleSourceTest.java", 100);
+    return moduleSource.createChild(new B(), partialCallStack);
+  }
+    
+  private ModuleSource createWithSizeThree() {
+    ModuleSource moduleSource = createWithSizeTwo();
+    StackTraceElement[] partialCallStack = new StackTraceElement[4];
+    partialCallStack[0] = BINDER_INSTALL;
+    partialCallStack[1] = new StackTraceElement("class1", "method1", "Class1.java", 1);
+    partialCallStack[2] = new StackTraceElement("class2", "method2", "Class2.java", 2);
+    partialCallStack[3] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$B", "configure", "moduleSourceTest.java", 200);
+    return moduleSource.createChild(new C(), partialCallStack);
+  }
+
+  private static class A extends AbstractModule {
+    @Override
+    public void configure() {
+      install(new B());
+    }
+  }
+  
+  private static class B implements Module {
+    @Override
+    public void configure(Binder binder) {
+      binder.install(new C());
+    }
+  }
+  
+  private static class C extends AbstractModule {
+    @Override
+    public void configure() {}
+  }
+}
diff --git a/core/test/com/google/inject/spi/ProviderMethodsTest.java b/core/test/com/google/inject/spi/ProviderMethodsTest.java
new file mode 100644
index 0000000..5814967
--- /dev/null
+++ b/core/test/com/google/inject/spi/ProviderMethodsTest.java
@@ -0,0 +1,952 @@
+/**
+ * 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 com.google.inject.spi;
+
+import static com.google.inject.Asserts.assertContains;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+import com.google.inject.Singleton;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.Errors;
+import com.google.inject.internal.InternalFlags;
+import com.google.inject.internal.ProviderMethod;
+import com.google.inject.internal.ProviderMethodsModule;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.util.Providers;
+import com.google.inject.util.Types;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ProviderMethodsTest extends TestCase implements Module {
+
+  @SuppressWarnings("unchecked")
+  public void testProviderMethods() {
+    Injector injector = Guice.createInjector(this);
+
+    Bob bob = injector.getInstance(Bob.class);
+    assertEquals("A Bob", bob.getName());
+
+    Bob clone = injector.getInstance(Bob.class);
+    assertEquals("A Bob", clone.getName());
+
+    assertNotSame(bob, clone);
+    assertSame(bob.getDaughter(), clone.getDaughter());
+
+    Key soleBobKey = Key.get(Bob.class, Sole.class);
+    assertSame(
+        injector.getInstance(soleBobKey),
+        injector.getInstance(soleBobKey)
+    );
+  }
+
+  public void configure(Binder binder) {}
+
+  interface Bob {
+    String getName();
+    Dagny getDaughter();
+  }
+
+  interface Dagny {
+    int getAge();
+  }
+
+  @Provides
+  Bob provideBob(final Dagny dagny) {
+    return new Bob() {
+      public String getName() {
+        return "A Bob";
+      }
+
+      public Dagny getDaughter() {
+        return dagny;
+      }
+    };
+  }
+
+  @Provides
+  @Singleton
+  @Sole
+  Bob provideSoleBob(final Dagny dagny) {
+    return new Bob() {
+      public String getName() {
+        return "Only Bob";
+      }
+
+      public Dagny getDaughter() {
+        return dagny;
+      }
+    };
+  }
+
+  @Provides
+  @Singleton
+  Dagny provideDagny() {
+    return new Dagny() {
+      public int getAge() {
+        return 1;
+      }
+    };
+  }
+
+  @Retention(RUNTIME)
+  @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+  @BindingAnnotation
+  @interface Sole {}
+
+
+
+// We'll have to make getProvider() support circular dependencies before this
+// will work.
+//
+//  public void testCircularDependency() {
+//    Injector injector = Guice.createInjector(new Module() {
+//      public void configure(Binder binder) {
+//        binder.install(ProviderMethods.from(ProviderMethodsTest.this));
+//      }
+//    });
+//
+//    Foo foo = injector.getInstance(Foo.class);
+//    assertEquals(5, foo.getI());
+//    assertEquals(10, foo.getBar().getI());
+//    assertEquals(5, foo.getBar().getFoo().getI());
+//  }
+//
+//  interface Foo {
+//    Bar getBar();
+//    int getI();
+//  }
+//
+//  interface Bar {
+//    Foo getFoo();
+//    int getI();
+//  }
+//
+//  @Provides Foo newFoo(final Bar bar) {
+//    return new Foo() {
+//
+//      public Bar getBar() {
+//        return bar;
+//      }
+//
+//      public int getI() {
+//        return 5;
+//      }
+//    };
+//  }
+//
+//  @Provides Bar newBar(final Foo foo) {
+//    return new Bar() {
+//
+//      public Foo getFoo() {
+//        return foo;
+//      }
+//
+//      public int getI() {
+//        return 10;
+//      }
+//    };
+//  }
+
+
+  public void testMultipleBindingAnnotations() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {}
+
+        @Provides @Named("A") @Blue
+        public String provideString() {
+          return "a";
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "more than one annotation annotated with @BindingAnnotation:", "Named", "Blue",
+          "at " + getClass().getName(), ".provideString(ProviderMethodsTest.java:");
+    }
+
+  }
+
+  @Retention(RUNTIME)
+  @BindingAnnotation @interface Blue {}
+
+  public void testGenericProviderMethods() {
+    Injector injector = Guice.createInjector(
+        new ProvideTs<String>("A", "B") {}, new ProvideTs<Integer>(1, 2) {});
+
+    assertEquals("A", injector.getInstance(Key.get(String.class, Names.named("First"))));
+    assertEquals("B", injector.getInstance(Key.get(String.class, Names.named("Second"))));
+    assertEquals(ImmutableSet.of("A", "B"),
+        injector.getInstance(Key.get(Types.setOf(String.class))));
+
+    assertEquals(1, injector.getInstance(Key.get(Integer.class, Names.named("First"))).intValue());
+    assertEquals(2, injector.getInstance(Key.get(Integer.class, Names.named("Second"))).intValue());
+    assertEquals(ImmutableSet.of(1, 2),
+        injector.getInstance(Key.get(Types.setOf(Integer.class))));
+  }
+
+  abstract class ProvideTs<T> extends AbstractModule {
+    final T first;
+    final T second;
+
+    protected ProvideTs(T first, T second) {
+      this.first = first;
+      this.second = second;
+    }
+
+    @Override protected void configure() {}
+
+    @Named("First") @Provides T provideFirst() {
+      return first;
+    }
+
+    @Named("Second") @Provides T provideSecond() {
+      return second;
+    }
+
+    @Provides Set<T> provideBoth(@Named("First") T first, @Named("Second") T second) {
+      return ImmutableSet.of(first, second);
+    }
+  }
+
+  public void testAutomaticProviderMethods() {
+    Injector injector = Guice.createInjector((Module) new AbstractModule() {
+      @Override protected void configure() { }
+      private int next = 1;
+
+      @Provides @Named("count")
+      public Integer provideCount() {
+        return next++;
+      }
+    });
+
+    assertEquals(1, injector.getInstance(Key.get(Integer.class, Names.named("count"))).intValue());
+    assertEquals(2, injector.getInstance(Key.get(Integer.class, Names.named("count"))).intValue());
+    assertEquals(3, injector.getInstance(Key.get(Integer.class, Names.named("count"))).intValue());
+  }
+
+  /**
+   * If the user installs provider methods for the module manually, that shouldn't cause a double
+   * binding of the provider methods' types.
+   */
+  public void testAutomaticProviderMethodsDoNotCauseDoubleBinding() {
+    Module installsSelf = new AbstractModule() {
+      @Override protected void configure() {
+        install(this);
+        bind(Integer.class).toInstance(5);
+      }
+      @Provides public String provideString(Integer count) {
+        return "A" + count;
+      }
+    };
+
+    Injector injector = Guice.createInjector(installsSelf);
+    assertEquals("A5", injector.getInstance(String.class));
+  }
+
+  public void testWildcardProviderMethods() {
+    final List<String> strings = ImmutableList.of("A", "B", "C");
+    final List<Number> numbers = ImmutableList.<Number>of(1, 2, 3);
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        @SuppressWarnings("unchecked")
+        Key<List<? super Integer>> listOfSupertypesOfInteger = (Key<List<? super Integer>>)
+            Key.get(Types.listOf(Types.supertypeOf(Integer.class)));
+        bind(listOfSupertypesOfInteger).toInstance(numbers);
+      }
+      @Provides public List<? extends CharSequence> provideCharSequences() {
+        return strings;
+      }
+      @Provides public Class<?> provideType() {
+        return Float.class;
+      }
+    });
+
+    assertSame(strings, injector.getInstance(HasWildcardInjection.class).charSequences);
+    assertSame(numbers, injector.getInstance(HasWildcardInjection.class).numbers);
+    assertSame(Float.class, injector.getInstance(HasWildcardInjection.class).type);
+  }
+
+  static class HasWildcardInjection {
+    @Inject List<? extends CharSequence> charSequences;
+    @Inject List<? super Integer> numbers;
+    @Inject Class<?> type;
+  }
+
+  public void testProviderMethodDependenciesAreExposed() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        bind(Integer.class).toInstance(50);
+        bindConstant().annotatedWith(Names.named("units")).to("Kg");
+      }
+      @Provides @Named("weight") String provideWeight(Integer count, @Named("units") String units) {
+        return count + units;
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    ProviderInstanceBinding<?> binding = (ProviderInstanceBinding<?>) injector.getBinding(
+        Key.get(String.class, Names.named("weight")));
+    Method method =
+      module.getClass().getDeclaredMethod("provideWeight", Integer.class, String.class);
+    InjectionPoint point = new InjectionPoint(TypeLiteral.get(module.getClass()), method, false);
+    assertEquals(ImmutableSet.<Dependency<?>>of(
+        new Dependency<Integer>(point, Key.get(Integer.class), false, 0),
+        new Dependency<String>(point, Key.get(String.class, Names.named("units")), false, 1)),
+         binding.getDependencies());
+  }
+
+  public void testNonModuleProviderMethods() {
+    final Object methodsObject = new Object() {
+      @Provides @Named("foo") String provideFoo() {
+        return "foo-value";
+      }
+    };
+
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        install(ProviderMethodsModule.forObject(methodsObject));
+      }
+    };
+
+    Injector injector = Guice.createInjector(module);
+
+    Key<String> key = Key.get(String.class, Names.named("foo"));
+    assertEquals("foo-value", injector.getInstance(key));
+
+    // Test the provider method object itself. This makes sure getInstance works, since GIN uses it
+    List<Element> elements = Elements.getElements(module);
+    assertEquals(1, elements.size());
+
+    Element element = elements.get(0);
+    assertTrue(element + " instanceof ProviderInstanceBinding",
+        element instanceof ProviderInstanceBinding);
+
+    ProviderInstanceBinding binding = (ProviderInstanceBinding) element;
+    javax.inject.Provider provider = binding.getUserSuppliedProvider();
+    assertTrue(provider instanceof ProviderMethod);
+    assertEquals(methodsObject, ((ProviderMethod) provider).getInstance());
+    assertSame(provider, binding.getProviderInstance());
+  }
+
+  public void testVoidProviderMethods() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {}
+
+        @Provides void provideFoo() {}
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Provider methods must return a value. Do not return void.",
+          getClass().getName(), ".provideFoo(ProviderMethodsTest.java:");
+    }
+  }
+
+  public void testInjectsJustOneLogger() {
+    AtomicReference<Logger> loggerRef = new AtomicReference<Logger>();
+    Injector injector = Guice.createInjector(new FooModule(loggerRef));
+
+    assertNull(loggerRef.get());
+    injector.getInstance(Integer.class);
+    Logger lastLogger = loggerRef.getAndSet(null);
+    assertNotNull(lastLogger);
+    injector.getInstance(Integer.class);
+    assertSame(lastLogger, loggerRef.get());
+
+    assertEquals(FooModule.class.getName(), lastLogger.getName());
+  }
+
+  private static class FooModule extends AbstractModule {
+    private final AtomicReference<Logger> loggerRef;
+
+    public FooModule(AtomicReference<Logger> loggerRef) {
+      this.loggerRef = loggerRef;
+    }
+
+    @Override protected void configure() {}
+
+    @SuppressWarnings("unused")
+    @Provides Integer foo(Logger logger) {
+      loggerRef.set(logger);
+      return 42;
+    }
+  }
+
+  public void testSpi() throws Exception {
+    Module m1 = new AbstractModule() {
+      @Override protected void configure() {}
+      @Provides @Named("foo") String provideFoo(Integer dep) { return "foo"; }
+    };
+    Module m2 = new AbstractModule() {
+      @Override protected void configure() {}
+      @Provides Integer provideInt(@Named("foo") String dep) { return 42; }
+    };
+    Injector injector = Guice.createInjector(m1, m2);
+
+    Binding<String> stringBinding =
+        injector.getBinding(Key.get(String.class, Names.named("foo")));
+    ProvidesMethodBinding<String> stringMethod =
+        stringBinding.acceptTargetVisitor(new BindingCapturer<String>());
+    assertEquals(m1, stringMethod.getEnclosingInstance());
+    assertEquals(m1.getClass().getDeclaredMethod("provideFoo", Integer.class),
+        stringMethod.getMethod());
+    assertEquals(((HasDependencies) stringBinding).getDependencies(),
+        stringMethod.getDependencies());
+    assertEquals(Key.get(String.class, Names.named("foo")), stringMethod.getKey());
+
+    Binding<Integer> intBinding = injector.getBinding(Integer.class);
+    ProvidesMethodBinding<Integer> intMethod =
+        intBinding.acceptTargetVisitor(new BindingCapturer<Integer>());
+    assertEquals(m2, intMethod.getEnclosingInstance());
+    assertEquals(m2.getClass().getDeclaredMethod("provideInt", String.class),
+        intMethod.getMethod());
+    assertEquals(((HasDependencies) intBinding).getDependencies(),
+        intMethod.getDependencies());
+    assertEquals(Key.get(Integer.class), intMethod.getKey());
+
+  }
+
+  private static class BindingCapturer<T> extends DefaultBindingTargetVisitor<T, ProvidesMethodBinding<T>>
+      implements ProvidesMethodTargetVisitor<T, ProvidesMethodBinding<T>> {
+
+    @SuppressWarnings("unchecked")
+    public ProvidesMethodBinding<T> visit(
+        ProvidesMethodBinding<? extends T> providesMethodBinding) {
+      return (ProvidesMethodBinding<T>)providesMethodBinding;
+    }
+
+    @Override protected ProvidesMethodBinding<T> visitOther(Binding<? extends T> binding) {
+      throw new IllegalStateException("unexpected visit of: " + binding);
+    }
+  }
+
+  public void testProvidesMethodVisibility() {
+    Injector injector = Guice.createInjector(new VisibilityModule());
+
+    assertEquals(42, injector.getInstance(Integer.class).intValue());
+    assertEquals(42L, injector.getInstance(Long.class).longValue());
+    assertEquals(42D, injector.getInstance(Double.class).doubleValue());
+    assertEquals(42F, injector.getInstance(Float.class).floatValue());
+  }
+
+  private static class VisibilityModule extends AbstractModule {
+    @Override protected void configure() {}
+
+    @SuppressWarnings("unused")
+    @Provides Integer foo() {
+      return 42;
+    }
+
+    @SuppressWarnings("unused")
+    @Provides private Long bar() {
+      return 42L;
+    }
+
+    @SuppressWarnings("unused")
+    @Provides protected Double baz() {
+      return 42D;
+    }
+
+    @SuppressWarnings("unused")
+    @Provides public Float quux() {
+      return 42F;
+    }
+  }
+
+  public void testProvidesMethodInheritenceHierarchy() {
+    try {
+      Guice.createInjector(new Sub1Module(), new Sub2Module());
+      fail("Expected injector creation failure");
+    } catch (CreationException expected) {
+      // both of our super class bindings cause errors
+      assertContains(expected.getMessage(),
+          "A binding to java.lang.Long was already configured",
+          "A binding to java.lang.Integer was already configured");
+    }
+  }
+
+  public void testProvidesMethodsDefinedInSuperClass() {
+    Injector injector = Guice.createInjector(new Sub1Module());
+    assertEquals(42, injector.getInstance(Integer.class).intValue());
+    assertEquals(42L, injector.getInstance(Long.class).longValue());
+    assertEquals(42D, injector.getInstance(Double.class).doubleValue());
+  }
+
+  private static class BaseModule extends AbstractModule {
+    @Override protected void configure() {}
+
+    @Provides Integer foo() {
+      return 42;
+    }
+
+    @Provides Long bar() {
+      return 42L;
+    }
+  }
+
+  private static class Sub1Module extends BaseModule {
+    @Provides Double baz() {
+      return 42D;
+    }
+  }
+
+  private static class Sub2Module extends BaseModule {
+    @Provides Float quux() {
+      return 42F;
+    }
+  }
+
+  /*if[AOP]*/
+  public void testShareFastClass() {
+    CallerInspecterModule module = new CallerInspecterModule();
+    Guice.createInjector(Stage.PRODUCTION, module);
+    assertEquals(module.fooCallerClass, module.barCallerClass);
+    assertTrue(module.fooCallerClass.contains("$$FastClassByGuice$$"));
+  }
+
+  private static class CallerInspecterModule extends AbstractModule {
+    // start them off as unequal
+    String barCallerClass = "not_set_bar";
+    String fooCallerClass = "not_set_foo";
+
+    @Override protected void configure() {}
+
+    @Provides @Singleton Integer foo() {
+      this.fooCallerClass = new Exception().getStackTrace()[1].getClassName();
+      return 42;
+    }
+
+    @Provides @Singleton Long bar() {
+      this.barCallerClass = new Exception().getStackTrace()[1].getClassName();
+      return 42L;
+    }
+  }
+
+  public void testShareFastClassWithSuperClass() {
+    CallerInspecterSubClassModule module = new CallerInspecterSubClassModule();
+    Guice.createInjector(Stage.PRODUCTION, module);
+    assertEquals("Expected provider methods in the same class to share fastclass classes",
+        module.fooCallerClass, module.barCallerClass);
+    assertFalse(
+        "Did not expect provider methods in the subclasses to share fastclass classes "
+            + "with their parent classes",
+        module.bazCallerClass.equals(module.barCallerClass));
+  }
+
+
+  private static class CallerInspecterSubClassModule extends CallerInspecterModule {
+    String bazCallerClass;
+
+    @Override protected void configure() {}
+
+    @Provides @Singleton Double baz() {
+      this.bazCallerClass = new Exception().getStackTrace()[1].getClassName();
+      return 42D;
+    }
+  }
+  /*end[AOP]*/
+
+  static class SuperClassModule extends AbstractModule {
+    @Override protected void configure() {}
+    @Provides Number providerMethod() {
+      return 1D;
+    }
+    @Provides @Named("rawlist") List rawProvider(@Named("list") List<String> f) {
+      return f;
+    }
+
+    @Provides @Named("unrawlist") List<String> rawParameterProvider(@Named("rawlist") List f) {
+      return f;
+    }
+
+    @Provides @Named("list") List<String> annotatedGenericProviderMethod() {
+      return new ArrayList<String>();
+    }
+    @Provides @Named("collection") Collection<String> annotatedGenericParameterProviderMethod(
+        @Named("list") List<String> foo) {
+      return foo;
+    }
+    @Provides private String privateProviderMethod() {
+      return "hello";
+    }
+  }
+
+  public void testOverrideProviderMethod_overrideHasProvides() {
+    class SubClassModule extends SuperClassModule {
+      @Override @Provides Number providerMethod() {
+        return 2D;
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()",
+          "overridden by: " + SubClassModule.class.getName() + ".providerMethod()");
+    }
+  }
+
+  public void testOverrideProviderMethod_overrideHasProvides_withNewAnnotation() {
+    class SubClassModule extends SuperClassModule {
+      @Override @Provides @Named("foo") Number providerMethod() {
+        return 2D;
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()",
+          "overridden by: " + SubClassModule.class.getName() + ".providerMethod()");
+    }
+  }
+
+  public void testOverrideProviderMethod_overrideDoesntHaveProvides() {
+    class SubClassModule extends SuperClassModule {
+      @Override Number providerMethod() {
+        return 2D;
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()",
+          "overridden by: " + SubClassModule.class.getName() + ".providerMethod()");
+    }
+  }
+  public void testOverrideProviderMethod_overrideDoesntHaveProvides_withNewAnnotation() {
+    class SubClassModule extends SuperClassModule {
+      @Override @Named("foo") Number providerMethod() {
+        return 2D;
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()",
+          "overridden by: " + SubClassModule.class.getName() + ".providerMethod()");
+    }
+  }
+
+
+  public void testOverrideProviderMethod_covariantOverrideDoesntHaveProvides() {
+    class SubClassModule extends SuperClassModule {
+      @Override Double providerMethod() {
+        return 2D;
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()",
+          "overridden by: " + SubClassModule.class.getName() + ".providerMethod()");
+    }
+  }
+
+  public void testOverrideProviderMethod_covariantOverrideHasProvides() {
+    class SubClassModule extends SuperClassModule {
+      @Override @Provides Double providerMethod() {
+        return 2D;
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName() + ".providerMethod()",
+          "overridden by: " + SubClassModule.class.getName() + ".providerMethod()");
+    }
+  }
+
+  public void testOverrideProviderMethod_fakeOverridePrivateMethod() {
+    class SubClassModule extends SuperClassModule {
+      // not actually an override, just looks like it
+      String privateProviderMethod() {
+        return "sub";
+      }
+    }
+    assertEquals("hello", Guice.createInjector(new SubClassModule()).getInstance(String.class));
+  }
+
+  public void testOverrideProviderMethod_subclassRawTypes_returnType() {
+    class SubClassModule extends SuperClassModule {
+      @Override List annotatedGenericProviderMethod() {
+        return super.annotatedGenericProviderMethod();
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName()
+              + ".annotatedGenericProviderMethod()",
+          "overridden by: " + SubClassModule.class.getName() + ".annotatedGenericProviderMethod()");
+    }
+  }
+
+  public void testOverrideProviderMethod_subclassRawTypes_parameterType() {
+    class SubClassModule extends SuperClassModule {
+      @Override Collection<String> annotatedGenericParameterProviderMethod(List foo) {
+        return super.annotatedGenericParameterProviderMethod(foo);
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName()
+              + ".annotatedGenericParameterProviderMethod()",
+          "overridden by: " + SubClassModule.class.getName()
+              + ".annotatedGenericParameterProviderMethod()");
+    }
+  }
+
+  public void testOverrideProviderMethod_superclassRawTypes_returnType() {
+    class SubClassModule extends SuperClassModule {
+      // remove the rawtype from the override
+      @Override List<String> rawProvider(List<String> f) {
+        return f;
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + SuperClassModule.class.getName() + ".rawProvider()",
+          "overridden by: " + SubClassModule.class.getName() + ".rawProvider()");
+    }
+  }
+
+  abstract static class GenericSuperModule<T> extends AbstractModule {
+    @Provides String provide(T thing) {
+      return thing.toString();
+    }
+  }
+
+  // This is a tricky case where signatures don't match, but it is an override (facilitated via a
+  // bridge method)
+  public void testOverrideProviderMethod_erasureBasedOverrides() {
+    class SubClassModule extends GenericSuperModule<Integer> {
+      @Override String provide(Integer thing) {
+        return thing.toString();
+      }
+
+      @Override protected void configure() {
+        bind(Integer.class).toInstance(3);
+      }
+    }
+    try {
+      Guice.createInjector(new SubClassModule());
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Overriding @Provides methods is not allowed.",
+          "@Provides method: " + GenericSuperModule.class.getName() + ".provide()",
+          "overridden by: " + SubClassModule.class.getName() + ".provide()");
+    }
+  }
+
+  class RestrictedSuper extends AbstractModule {
+    @Provides public String provideFoo() { return "foo"; }
+    @Override protected void configure() {}
+  }
+
+  public class ExposedSub extends RestrictedSuper {}
+
+  public void testOverrideProviderMethod_increasedVisibility() {
+    // ensure we don't detect the synthetic provideFoo method in ExposedSub as an override (it is,
+    // but since it is synthetic it would be annoying to throw an error on it).
+    assertEquals("foo", Guice.createInjector(new ExposedSub()).getInstance(String.class));
+  }
+
+  interface ProviderInterface<T> {
+    T getT();
+  }
+
+  static class ModuleImpl extends AbstractModule implements ProviderInterface<String> {
+    @Override protected void configure() {}
+    @Provides public String getT() {
+      return "string";
+    }
+    @Provides public Object getObject() {
+      return new Object();
+    }
+    /* javac will synthesize a bridge method for getT with the types erased, equivalent to:
+     * @Provides public Object getT() { ... }
+     */
+  }
+
+  public void testIgnoreSyntheticBridgeMethods() {
+    Guice.createInjector(new ModuleImpl());
+  }
+
+  public void testNullability() throws Exception {
+    Module module = new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toProvider(Providers.<String>of(null));
+      }
+
+      @SuppressWarnings("unused")
+      @Provides
+      Integer fail(String foo) {
+        return 1;
+      }
+
+      @SuppressWarnings("unused")
+      @Provides
+      Long succeed(@Nullable String foo) {
+        return 2L;
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    InjectionPoint fooPoint = InjectionPoint.forMethod(
+        module.getClass().getDeclaredMethod("fail", String.class),
+        TypeLiteral.get(module.getClass()));
+    Dependency<?> fooDependency = Iterables.getOnlyElement(fooPoint.getDependencies());
+
+    runNullableTest(injector, fooDependency, module);
+
+    injector.getInstance(Long.class);
+  }
+
+  private void runNullableTest(Injector injector, Dependency<?> dependency, Module module) {
+    switch (InternalFlags.getNullableProvidesOption()) {
+      case ERROR:
+        validateNullableFails(injector, module);
+        break;
+      case IGNORE:
+        validateNullableIgnored(injector);
+        break;
+      case WARN:
+        validateNullableWarns(injector, dependency);
+        break;
+    }
+  }
+
+  private void validateNullableFails(Injector injector, Module module) {
+    try {
+      injector.getInstance(Integer.class);
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "1) null returned by binding at " + module.getClass().getName() + ".configure(",
+          "but parameter 0 of " + module.getClass().getName() + ".fail() is not @Nullable",
+          "while locating java.lang.String",
+          "for parameter 0 at " + module.getClass().getName() + ".fail(",
+          "while locating java.lang.Integer");
+
+      assertEquals(1, expected.getErrorMessages().size());
+    }
+  }
+
+  private void validateNullableIgnored(Injector injector) {
+    injector.getInstance(Integer.class); // no exception
+  }
+
+  private void validateNullableWarns(Injector injector, Dependency<?> dependency) {
+    final List<LogRecord> logRecords = Lists.newArrayList();
+    final Handler fakeHandler = new Handler() {
+      @Override
+      public void publish(LogRecord logRecord) {
+        logRecords.add(logRecord);
+      }
+      @Override
+      public void flush() {}
+      @Override
+      public void close() throws SecurityException {}
+    };
+    Logger.getLogger(Guice.class.getName()).addHandler(fakeHandler);
+    try {
+      injector.getInstance(Integer.class); // no exception, but assert it does log.
+      LogRecord record = Iterables.getOnlyElement(logRecords);
+      assertEquals(
+          "Guice injected null into parameter {0} of {1} (a {2}), please mark it @Nullable."
+              + " Use -Dguice_check_nullable_provides_params=ERROR to turn this into an"
+              + " error.",
+          record.getMessage());
+      assertEquals(dependency.getParameterIndex(), record.getParameters()[0]);
+      assertEquals(Errors.convert(dependency.getInjectionPoint().getMember()),
+          record.getParameters()[1]);
+      assertEquals(Errors.convert(dependency.getKey()), record.getParameters()[2]);
+    } finally {
+      Logger.getLogger(Guice.class.getName()).removeHandler(fakeHandler);
+    }
+  }
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @interface Nullable {}
+}
diff --git a/core/test/com/google/inject/spi/SpiBindingsTest.java b/core/test/com/google/inject/spi/SpiBindingsTest.java
new file mode 100644
index 0000000..82e969e
--- /dev/null
+++ b/core/test/com/google/inject/spi/SpiBindingsTest.java
@@ -0,0 +1,463 @@
+/**
+ * Copyright (C) 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.inject.spi;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.getDeclaringSourcePart;
+import static com.google.inject.Asserts.isIncludeStackTraceComplete;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.Scopes;
+import com.google.inject.Singleton;
+import com.google.inject.Stage;
+import com.google.inject.name.Names;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.lang.reflect.Constructor;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Logger;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class SpiBindingsTest extends TestCase {
+
+  public void testBindConstant() {
+    checkInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bindConstant().annotatedWith(Names.named("one")).to(1);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertTrue(binding instanceof InstanceBinding);
+            assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testToInstanceBinding() {
+    checkInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).toInstance("A");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertTrue(binding instanceof InstanceBinding);
+            checkBindingSource(binding);
+            assertEquals(Key.get(String.class), binding.getKey());
+            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(InstanceBinding<? extends T> binding) {
+                assertEquals("A", binding.getInstance());
+                return null;
+              }
+            });
+            binding.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              public Void visitEagerSingleton() {
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testToProviderBinding() {
+    final Provider<String> stringProvider = new StringProvider();
+
+    checkInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).toProvider(stringProvider);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertTrue(binding instanceof ProviderInstanceBinding);
+            checkBindingSource(binding);
+            assertEquals(Key.get(String.class), binding.getKey());
+            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(
+                  ProviderInstanceBinding<? extends T> binding) {
+                assertSame(stringProvider, binding.getUserSuppliedProvider());
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testToProviderKeyBinding() {
+    checkInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).toProvider(StringProvider.class);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertTrue(binding instanceof ProviderKeyBinding);
+            checkBindingSource(binding);
+            assertEquals(Key.get(String.class), binding.getKey());
+            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(ProviderKeyBinding<? extends T> binding) {
+                assertEquals(Key.get(StringProvider.class), binding.getProviderKey());
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testToKeyBinding() {
+    final Key<String> aKey = Key.get(String.class, Names.named("a"));
+    final Key<String> bKey = Key.get(String.class, Names.named("b"));
+
+    checkInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bind(aKey).to(bKey);
+            bind(bKey).toInstance("B");
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertTrue(binding instanceof LinkedKeyBinding);
+            checkBindingSource(binding);
+            assertEquals(aKey, binding.getKey());
+            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(LinkedKeyBinding<? extends T> binding) {
+                assertEquals(bKey, binding.getLinkedKey());
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertEquals(bKey, binding.getKey());
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testToConstructorBinding() {
+    checkInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bind(D.class);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertTrue(binding instanceof ConstructorBinding);
+            checkBindingSource(binding);
+            assertEquals(Key.get(D.class), binding.getKey());
+            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(ConstructorBinding<? extends T> binding) {
+                Constructor<?> expected = D.class.getDeclaredConstructors()[0];
+                assertEquals(expected, binding.getConstructor().getMember());
+                assertEquals(ImmutableSet.<InjectionPoint>of(), binding.getInjectableMembers());
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testConstantBinding() {
+    checkInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bindConstant().annotatedWith(Names.named("one")).to(1);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> binding) {
+            assertTrue(binding instanceof InstanceBinding);
+            checkBindingSource(binding);
+            assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
+            binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
+              @Override public Void visit(InstanceBinding<? extends T> binding) {
+                assertEquals(1, binding.getInstance());
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+
+  public void testConvertedConstantBinding() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindConstant().annotatedWith(Names.named("one")).to("1");
+      }
+    });
+
+    Binding<Integer> binding = injector.getBinding(Key.get(Integer.class, Names.named("one")));
+    assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
+    checkBindingSource(binding);
+    assertTrue(binding instanceof ConvertedConstantBinding);
+    binding.acceptTargetVisitor(new FailingTargetVisitor<Integer>() {
+      @Override public Void visit(
+          ConvertedConstantBinding<? extends Integer> binding) {
+        assertEquals((Integer) 1, binding.getValue());
+        assertEquals(Key.get(String.class, Names.named("one")), binding.getSourceKey());
+        return null;
+      }
+    });
+  }
+
+  public void testProviderBinding() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toInstance("A");
+      }
+    });
+
+    Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
+    Binding<Provider<String>> binding = injector.getBinding(providerOfStringKey);
+    assertEquals(providerOfStringKey, binding.getKey());
+    checkBindingSource(binding);
+    assertTrue(binding instanceof ProviderBinding);
+    binding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
+      @Override public Void visit(
+          ProviderBinding<? extends Provider<String>> binding) {
+        assertEquals(Key.get(String.class), binding.getProvidedKey());
+        return null;
+      }
+    });
+  }
+
+  public void testScopes() {
+    checkInjector(
+        new AbstractModule() {
+          protected void configure() {
+            bind(String.class).annotatedWith(Names.named("a"))
+                .toProvider(StringProvider.class).in(Singleton.class);
+            bind(String.class).annotatedWith(Names.named("b"))
+                .toProvider(StringProvider.class).in(Scopes.SINGLETON);
+            bind(String.class).annotatedWith(Names.named("c"))
+                .toProvider(StringProvider.class).asEagerSingleton();
+            bind(String.class).annotatedWith(Names.named("d"))
+                .toProvider(StringProvider.class);
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertEquals(Key.get(String.class, Names.named("a")), command.getKey());
+            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              @Override public Void visitScope(Scope scope) {
+                // even though we bound with an annotation, the injector always uses instances
+                assertSame(Scopes.SINGLETON, scope);
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertEquals(Key.get(String.class, Names.named("b")), command.getKey());
+            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              @Override public Void visitScope(Scope scope) {
+                assertSame(Scopes.SINGLETON, scope);
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertEquals(Key.get(String.class, Names.named("c")), command.getKey());
+            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              @Override public Void visitEagerSingleton() {
+                return null;
+              }
+            });
+            return null;
+          }
+        },
+
+        new FailingElementVisitor() {
+          @Override public <T> Void visit(Binding<T> command) {
+            assertEquals(Key.get(String.class, Names.named("d")), command.getKey());
+            command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
+              @Override public Void visitNoScoping() {
+                return null;
+              }
+            });
+            return null;
+          }
+        }
+    );
+  }
+  
+  public void testExtensionSpi() {
+    final AtomicBoolean visiting = new AtomicBoolean(false);
+    
+    final Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toProvider(new ProviderWithExtensionVisitor<String>() {
+          public <B, V> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor,
+              ProviderInstanceBinding<? extends B> binding) {
+            assertSame(this, binding.getUserSuppliedProvider());
+            // We can't always check for FailingSpiTargetVisitor,
+            // because constructing the injector visits here, and we need
+            // to process the binding as normal
+            if(visiting.get()) {
+              assertTrue("visitor: " + visitor, visitor instanceof FailingSpiTargetVisitor);
+              return (V)"visited";
+            } else {
+              return visitor.visit(binding);
+            }
+          }
+          
+          public String get() {
+            return "FooBar";
+          }
+        });
+      }
+    });
+    
+    visiting.set(true);
+
+    // Check for Provider<String> binding -- that is still a ProviderBinding.
+    Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
+    Binding<Provider<String>> providerBinding = injector.getBinding(providerOfStringKey);
+    assertEquals(providerOfStringKey, providerBinding.getKey());
+    checkBindingSource(providerBinding);
+    assertTrue("binding: " + providerBinding, providerBinding instanceof ProviderBinding);
+    providerBinding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
+      @Override public Void visit(ProviderBinding<? extends Provider<String>> binding) {
+        assertEquals(Key.get(String.class), binding.getProvidedKey());
+        return null;
+      }
+    });
+    
+    // Check for String binding -- that one is ProviderInstanceBinding, and gets hooked
+    Binding<String> binding = injector.getBinding(String.class);
+    assertEquals(Key.get(String.class), binding.getKey());
+    checkBindingSource(binding);
+    assertTrue(binding instanceof ProviderInstanceBinding);
+    assertEquals("visited", binding.acceptTargetVisitor(new FailingSpiTargetVisitor<String>()));
+  }
+
+  private static class FailingSpiTargetVisitor<T> extends DefaultBindingTargetVisitor<T, String> {
+    @Override
+    protected String visitOther(Binding<? extends T> binding) {
+      throw new AssertionFailedError();
+    }
+  }
+
+  public void checkBindingSource(Binding binding) {
+    assertContains(binding.getSource().toString(), getDeclaringSourcePart(getClass()));
+    ElementSource source = (ElementSource) binding.getSource();
+    assertFalse(source.getModuleClassNames().isEmpty());
+    if (isIncludeStackTraceComplete()) {
+      assertTrue(source.getStackTrace().length > 0);
+    } else {
+      assertEquals(0, source.getStackTrace().length);
+    }
+  }
+  
+  public void checkInjector(Module module, ElementVisitor<?>... visitors) {
+    Injector injector = Guice.createInjector(module);
+
+    List<Binding<?>> bindings = Lists.newArrayList(injector.getBindings().values());
+    for (Iterator<Binding<?>> i = bindings.iterator(); i.hasNext(); ) {
+      if (BUILT_IN_BINDINGS.contains(i.next().getKey())) {
+        i.remove();
+      }
+    }
+
+    Collections.sort(bindings, orderByKey);
+
+    assertEquals(bindings.size(), visitors.length);
+
+    for (int i = 0; i < visitors.length; i++) {
+      ElementVisitor<?> visitor = visitors[i];
+      Binding<?> binding = bindings.get(i);
+      binding.acceptVisitor(visitor);
+    }
+  }
+
+  private final ImmutableSet<Key<?>> BUILT_IN_BINDINGS = ImmutableSet.of(
+      Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class));
+
+  private final Comparator<Binding<?>> orderByKey = new Comparator<Binding<?>>() {
+    public int compare(Binding<?> a, Binding<?> b) {
+      return a.getKey().toString().compareTo(b.getKey().toString());
+    }
+  };
+
+  private static class StringProvider implements Provider<String> {
+    public String get() {
+      return "A";
+    }
+  }
+
+  private static class C { }
+
+  private static class D extends C {
+    @Inject public D(Injector unused) { }
+  }
+}
diff --git a/core/test/com/google/inject/spi/ToolStageInjectorTest.java b/core/test/com/google/inject/spi/ToolStageInjectorTest.java
new file mode 100644
index 0000000..7f63f1c
--- /dev/null
+++ b/core/test/com/google/inject/spi/ToolStageInjectorTest.java
@@ -0,0 +1,165 @@
+package com.google.inject.spi;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Asserts;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Stage;
+import com.google.inject.spi.Toolable;
+
+import junit.framework.TestCase;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class ToolStageInjectorTest extends TestCase {
+
+  @Override
+  protected void setUp() throws Exception {
+    Foo.s = null;
+    Foo.sm = null;
+  }
+
+  public void testToolStageInjectorRestrictions() {
+    Injector injector = Guice.createInjector(Stage.TOOL);
+    try {
+      injector.injectMembers(new Object());
+      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    try {
+      injector.getInstance(Injector.class);
+      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    try {
+      injector.getInstance(Key.get(Injector.class));
+      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    try {
+      injector.getProvider(Injector.class);
+      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    try {
+      injector.getProvider(Key.get(Injector.class));
+      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
+    } catch (UnsupportedOperationException expected) {
+    }
+  }
+  
+  public void testToolStageDoesntInjectInstances() {
+    final Foo foo = new Foo();
+    Guice.createInjector(Stage.TOOL, new AbstractModule() {
+      @Override
+      protected void configure() {
+        requestStaticInjection(Foo.class);
+        requestInjection(foo);
+      }
+    });
+    assertNull(Foo.s);
+    assertNull(Foo.sm);
+    assertNull(foo.f);
+    assertNull(foo.m);
+  }
+  
+  public void testToolStageDoesntInjectProviders() {
+    final Foo foo = new Foo();
+    Guice.createInjector(Stage.TOOL, new AbstractModule() {
+      @Override
+      protected void configure() {
+        requestStaticInjection(Foo.class);
+        bind(Object.class).toProvider(foo);
+      }
+    });
+    assertNull(Foo.s);
+    assertNull(Foo.sm);
+    assertNull(foo.f);
+    assertNull(foo.m);
+  }
+  
+  public void testToolStageWarnsOfMissingObjectGraph() {
+    final Bar bar = new Bar();
+    try {
+      Guice.createInjector(Stage.TOOL, new AbstractModule() {
+        @Override
+        protected void configure() {
+          requestStaticInjection(Bar.class);
+          requestInjection(bar);
+        }
+      });
+      fail("expected exception");
+    } catch(CreationException expected) {
+      Asserts.assertContains(expected.toString(), "No implementation for java.util.Collection was bound.",
+          "No implementation for java.util.Map was bound.",
+          "No implementation for java.util.List was bound.",
+          "No implementation for java.util.Set was bound.");
+    }
+  }
+  
+  public void testToolStageInjectsTooledMethods() {
+    final Tooled tooled = new Tooled();
+    Guice.createInjector(Stage.TOOL, new AbstractModule() {
+      @Override
+      protected void configure() {
+        requestStaticInjection(Tooled.class);
+        bind(Object.class).toProvider(tooled);
+      }
+    });
+    assertNull(Tooled.s);
+    assertNotNull(Tooled.sm);
+    assertNull(tooled.f);
+    assertNotNull(tooled.m);
+  }
+  
+  @SuppressWarnings("unchecked")
+  private static class Bar {
+    @SuppressWarnings("unused") @Inject private static List list;
+    @SuppressWarnings("unused") @Inject private Set set;
+    @SuppressWarnings("unused") @Inject void method(Collection c) {}
+    @SuppressWarnings("unused") @Inject static void staticMethod(Map map) {}
+  }
+  
+  private static class Foo implements Provider<Object> {
+    @Inject private static S s; 
+    @Inject private F f;
+    private M m;
+    @SuppressWarnings("unused") @Inject void method(M m) { this.m = m; }
+    private static SM sm;
+    @SuppressWarnings("unused") @Inject static void staticMethod(SM sm) { Tooled.sm = sm; }
+    
+    public Object get() {
+      return null;
+    }
+  }
+  
+  private static class Tooled implements Provider<Object> {
+    @Inject private static S s; 
+    @Inject private F f;
+    private M m;
+    @Toolable @SuppressWarnings("unused") @Inject void method(M m) { this.m = m; }
+    private static SM sm;
+    @Toolable @SuppressWarnings("unused") @Inject static void staticMethod(SM sm) { Tooled.sm = sm; }
+    
+    public Object get() {
+      return null;
+    }
+  }
+    
+  private static class S {}
+  private static class F {}
+  private static class M {}
+  private static class SM {}
+
+}
diff --git a/core/test/com/google/inject/util/NoopOverrideTest.java b/core/test/com/google/inject/util/NoopOverrideTest.java
new file mode 100644
index 0000000..9f65bf4
--- /dev/null
+++ b/core/test/com/google/inject/util/NoopOverrideTest.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 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.inject.util;
+
+import com.google.inject.Module;
+import com.google.inject.spi.ElementVisitor;
+import com.google.inject.spi.ElementsTest;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class NoopOverrideTest extends ElementsTest {
+
+  protected void checkModule(Module module, ElementVisitor<?>... visitors) {
+    Module overridden = Modules.override(module).with(Modules.EMPTY_MODULE);
+    super.checkModule(overridden, visitors);
+  }
+}
\ No newline at end of file
diff --git a/core/test/com/google/inject/util/OverrideModuleTest.java b/core/test/com/google/inject/util/OverrideModuleTest.java
new file mode 100644
index 0000000..16d7a2c
--- /dev/null
+++ b/core/test/com/google/inject/util/OverrideModuleTest.java
@@ -0,0 +1,731 @@
+/**
+ * Copyright (C) 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.inject.util;
+
+import static com.google.inject.Asserts.asModuleChain;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Guice.createInjector;
+import static com.google.inject.name.Names.named;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.CreationException;
+import com.google.inject.Exposed;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.PrivateModule;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.Scope;
+import com.google.inject.ScopeAnnotation;
+import com.google.inject.Stage;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ModuleAnnotatedMethodScanner;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.Date;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author sberlin@gmail.com (Sam Berlin)
+ */
+public class OverrideModuleTest extends TestCase {
+
+  private static final Key<String> key2 = Key.get(String.class, named("2"));
+  private static final Key<String> key3 = Key.get(String.class, named("3"));
+
+  private static final Module EMPTY_MODULE = new Module() {
+    public void configure(Binder binder) {}
+  };
+
+  public void testOverride() {
+    Injector injector = createInjector(Modules.override(newModule("A")).with(newModule("B")));
+    assertEquals("B", injector.getInstance(String.class));
+  }
+
+  public void testOverrideMultiple() {
+    Module module = Modules.override(newModule("A"), newModule(1), newModule(0.5f))
+        .with(newModule("B"), newModule(2), newModule(1.5d));
+    Injector injector = createInjector(module);
+    assertEquals("B", injector.getInstance(String.class));
+    assertEquals(2, injector.getInstance(Integer.class).intValue());
+    assertEquals(0.5f, injector.getInstance(Float.class));
+    assertEquals(1.5d, injector.getInstance(Double.class));
+  }
+
+  public void testOverrideUnmatchedTolerated() {
+    Injector injector = createInjector(Modules.override(EMPTY_MODULE).with(newModule("B")));
+    assertEquals("B", injector.getInstance(String.class));
+  }
+
+  public void testOverrideConstant() {
+    Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bindConstant().annotatedWith(named("Test")).to("A");
+      }
+    };
+
+    Module replacements = new AbstractModule() {
+      @Override protected void configure() {
+        bindConstant().annotatedWith(named("Test")).to("B");
+      }
+    };
+
+    Injector injector = createInjector(Modules.override(original).with(replacements));
+    assertEquals("B", injector.getInstance(Key.get(String.class, named("Test"))));
+  }
+
+  public void testGetProviderInModule() {
+    Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("A");
+        bind(key2).toProvider(getProvider(String.class));
+      }
+    };
+
+    Injector injector = createInjector(Modules.override(original).with(EMPTY_MODULE));
+    assertEquals("A", injector.getInstance(String.class));
+    assertEquals("A", injector.getInstance(key2));
+  }
+
+  public void testOverrideWhatGetProviderProvided() {
+    Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("A");
+        bind(key2).toProvider(getProvider(String.class));
+      }
+    };
+
+    Module replacements = newModule("B");
+
+    Injector injector = createInjector(Modules.override(original).with(replacements));
+    assertEquals("B", injector.getInstance(String.class));
+    assertEquals("B", injector.getInstance(key2));
+  }
+
+  public void testOverrideUsingOriginalsGetProvider() {
+    Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("A");
+        bind(key2).toInstance("B");
+      }
+    };
+
+    Module replacements = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toProvider(getProvider(key2));
+      }
+    };
+
+    Injector injector = createInjector(Modules.override(original).with(replacements));
+    assertEquals("B", injector.getInstance(String.class));
+    assertEquals("B", injector.getInstance(key2));
+  }
+
+  public void testOverrideOfOverride() {
+    Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("A1");
+        bind(key2).toInstance("A2");
+        bind(key3).toInstance("A3");
+      }
+    };
+
+    Module replacements1 = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("B1");
+        bind(key2).toInstance("B2");
+      }
+    };
+
+    Module overrides = Modules.override(original).with(replacements1);
+
+    Module replacements2 = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("C1");
+        bind(key3).toInstance("C3");
+      }
+    };
+
+    Injector injector = createInjector(Modules.override(overrides).with(replacements2));
+    assertEquals("C1", injector.getInstance(String.class));
+    assertEquals("B2", injector.getInstance(key2));
+    assertEquals("C3", injector.getInstance(key3));
+  }
+
+  static class OuterReplacementsModule extends AbstractModule {
+    @Override protected void configure() {
+      install(new InnerReplacementsModule());
+    }
+  }
+  static class InnerReplacementsModule extends AbstractModule {
+    @Override protected void configure() {
+      bind(String.class).toInstance("B");
+      bind(String.class).toInstance("C");
+    }
+  }
+  public void testOverridesTwiceFails() {
+    Module original = newModule("A");
+    Module replacements = new OuterReplacementsModule();
+    Module module = Modules.override(original).with(replacements);
+    try {
+      createInjector(module);
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "A binding to java.lang.String was already configured at "
+              + InnerReplacementsModule.class.getName(),
+          asModuleChain(Modules.OverrideModule.class,
+              OuterReplacementsModule.class, InnerReplacementsModule.class),
+          "at " + InnerReplacementsModule.class.getName(),
+          asModuleChain(Modules.OverrideModule.class,
+              OuterReplacementsModule.class, InnerReplacementsModule.class));
+    }
+  }
+
+  public void testOverridesDoesntFixTwiceBoundInOriginal() {
+    Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("A");
+        bind(String.class).toInstance("B");
+      }
+    };
+
+    Module replacements = new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).toInstance("C");
+      }
+    };
+
+    Module module = Modules.override(original).with(replacements);
+    try {
+      createInjector(module);
+      fail();
+    } catch (CreationException expected) {
+      // The replacement comes first because we replace A with C,
+      // then we encounter B and freak out.
+      assertContains(expected.getMessage(),
+          "1) A binding to java.lang.String was already configured at "
+              + replacements.getClass().getName(),
+          asModuleChain(Modules.OverrideModule.class, replacements.getClass()),
+          "at " + original.getClass().getName(),
+          asModuleChain(Modules.OverrideModule.class, original.getClass()));
+    }
+  }
+
+  public void testStandardScopeAnnotation() {
+    final SingleUseScope scope = new SingleUseScope();
+
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(TestScopeAnnotation.class, scope);
+        bind(String.class).in(TestScopeAnnotation.class);
+      }
+    };
+    assertFalse(scope.used);
+
+    Guice.createInjector(module);
+    assertTrue(scope.used);
+  }
+
+  public void testOverrideUntargettedBinding() {
+    Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bind(Date.class);
+      }
+    };
+
+    Module replacements = new AbstractModule() {
+      @Override protected void configure() {
+        bind(Date.class).toInstance(new Date(0));
+      }
+    };
+
+    Injector injector = createInjector(Modules.override(original).with(replacements));
+    assertEquals(0, injector.getInstance(Date.class).getTime());
+  }
+
+  public void testOverrideScopeAnnotation() {
+    final Scope scope = new Scope() {
+      public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
+        throw new AssertionError("Should not be called");
+      }
+    };
+
+    final SingleUseScope replacementScope = new SingleUseScope();
+
+    Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(TestScopeAnnotation.class, scope);
+        bind(Date.class).in(TestScopeAnnotation.class);
+      }
+    };
+
+    Module replacements = new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(TestScopeAnnotation.class, replacementScope);
+      }
+    };
+
+    Injector injector = createInjector(Modules.override(original).with(replacements));
+    injector.getInstance(Date.class);
+    assertTrue(replacementScope.used);
+  }
+
+  public void testFailsIfOverridenScopeInstanceHasBeenUsed() {
+    final Scope scope = new Scope() {
+      public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
+        return unscoped;
+      }
+
+      @Override public String toString() {
+        return "ORIGINAL SCOPE";
+      }
+    };
+
+    final Module original = new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(TestScopeAnnotation.class, scope);
+        bind(Date.class).in(scope);
+        bind(String.class).in(scope);
+      }
+    };
+    Module originalWrapper = new AbstractModule() {
+      @Override protected void configure() {
+        install(original);
+      }
+    };
+
+    Module replacements = new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(TestScopeAnnotation.class, new SingleUseScope());
+      }
+    };
+
+    try {
+      createInjector(Modules.override(originalWrapper).with(replacements));
+      fail("Exception expected");
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "1) The scope for @TestScopeAnnotation is bound directly and cannot be overridden.",
+          "original binding at " + original.getClass().getName() + ".configure(",
+          asModuleChain(originalWrapper.getClass(), original.getClass()),
+          "bound directly at " + original.getClass().getName() + ".configure(",
+          asModuleChain(originalWrapper.getClass(), original.getClass()),
+          "bound directly at " + original.getClass().getName() + ".configure(",
+          asModuleChain(originalWrapper.getClass(), original.getClass()),          
+          "at ", replacements.getClass().getName() + ".configure(",
+          asModuleChain(Modules.OverrideModule.class, replacements.getClass()));
+    }
+  }
+
+  public void testOverrideIsLazy() {
+    final AtomicReference<String> value = new AtomicReference<String>("A");
+    Module overridden = Modules.override(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).annotatedWith(named("original")).toInstance(value.get());
+      }
+    }).with(new AbstractModule() {
+      @Override protected void configure() {
+        bind(String.class).annotatedWith(named("override")).toInstance(value.get());
+      }
+    });
+
+    // the value.get() call should be deferred until Guice.createInjector
+    value.set("B");
+    Injector injector = Guice.createInjector(overridden);
+    assertEquals("B", injector.getInstance(Key.get(String.class, named("original"))));
+    assertEquals("B", injector.getInstance(Key.get(String.class, named("override"))));
+  }
+
+  public void testOverridePrivateModuleOverPrivateModule() {
+    Module exposes5and6 = new AbstractModule() {
+      @Override protected void configure() {
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            bind(Integer.class).toInstance(5);
+            expose(Integer.class);
+
+            bind(Character.class).toInstance('E');
+          }
+        });
+
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            bind(Long.class).toInstance(6L);
+            expose(Long.class);
+
+            bind(Character.class).toInstance('F');
+          }
+        });
+      }
+    };
+
+    AbstractModule exposes15 = new AbstractModule() {
+      @Override protected void configure() {
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            bind(Integer.class).toInstance(15);
+            expose(Integer.class);
+
+            bind(Character.class).toInstance('G');
+          }
+        });
+
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            bind(Character.class).toInstance('H');
+          }
+        });
+      }
+    };
+
+    // override forwards
+    Injector injector = Guice.createInjector(Modules.override(exposes5and6).with(exposes15));
+    assertEquals(15, injector.getInstance(Integer.class).intValue());
+    assertEquals(6L, injector.getInstance(Long.class).longValue());
+
+    // and in reverse order
+    Injector reverse = Guice.createInjector(Modules.override(exposes15).with(exposes5and6));
+    assertEquals(5, reverse.getInstance(Integer.class).intValue());
+    assertEquals(6L, reverse.getInstance(Long.class).longValue());
+  }
+
+  public void testOverrideModuleAndPrivateModule() {
+    Module exposes5 = new PrivateModule() {
+      @Override protected void configure() {
+        bind(Integer.class).toInstance(5);
+        expose(Integer.class);
+      }
+    };
+
+    Module binds15 = new AbstractModule() {
+      @Override protected void configure() {
+        bind(Integer.class).toInstance(15);
+      }
+    };
+
+    Injector injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
+    assertEquals(15, injector.getInstance(Integer.class).intValue());
+
+    Injector reverse = Guice.createInjector(Modules.override(binds15).with(exposes5));
+    assertEquals(5, reverse.getInstance(Integer.class).intValue());
+  }
+
+  public void testOverrideDeepExpose() {
+    final AtomicReference<Provider<Character>> charAProvider
+        = new AtomicReference<Provider<Character>>();
+
+    Module exposes5 = new PrivateModule() {
+      @Override protected void configure() {
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            bind(Integer.class).toInstance(5);
+            expose(Integer.class);
+            charAProvider.set(getProvider(Character.class));
+            bind(Character.class).toInstance('A');
+          }
+        });
+        expose(Integer.class);
+      }
+    };
+
+    Injector injector = Guice.createInjector(Modules.override(exposes5).with(EMPTY_MODULE));
+    assertEquals(5, injector.getInstance(Integer.class).intValue());
+    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
+
+    injector = Guice.createInjector(Modules.override(EMPTY_MODULE).with(exposes5));
+    assertEquals(5, injector.getInstance(Integer.class).intValue());
+    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
+
+    final AtomicReference<Provider<Character>> charBProvider
+        = new AtomicReference<Provider<Character>>();
+
+    Module binds15 = new AbstractModule() {
+      @Override protected void configure() {
+        bind(Integer.class).toInstance(15);
+
+        install(new PrivateModule() {
+          @Override protected void configure() {
+            charBProvider.set(getProvider(Character.class));
+            bind(Character.class).toInstance('B');
+          }
+        });
+      }
+    };
+
+    injector = Guice.createInjector(Modules.override(binds15).with(exposes5));
+    assertEquals(5, injector.getInstance(Integer.class).intValue());
+    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
+    assertEquals('B', charBProvider.getAndSet(null).get().charValue());
+
+    injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
+    assertEquals(15, injector.getInstance(Integer.class).intValue());
+    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
+    assertEquals('B', charBProvider.getAndSet(null).get().charValue());
+  }
+
+  @Retention(RUNTIME)
+  @Target(TYPE)
+  @ScopeAnnotation
+  private static @interface TestScopeAnnotation {}
+
+  private static class SingleUseScope implements Scope {
+    boolean used = false;
+    public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
+      assertFalse(used);
+      used = true;
+      return unscoped;
+    }
+  }
+  
+  static class NewModule<T> extends AbstractModule {
+    private final T bound;
+    NewModule(T bound) {
+      this.bound = bound;
+    }
+    @Override protected void configure() {
+      @SuppressWarnings("unchecked")
+      Class<T> type = (Class<T>)bound.getClass();
+      bind(type).toInstance(bound);
+    }
+  }
+
+  private static <T> Module newModule(final T bound) {
+    return new NewModule<T>(bound);
+  }
+  
+  private static final String RESULT = "RESULT";
+  private static final String PRIVATE_INPUT = "PRIVATE_INPUT";
+  private static final String OVERRIDDEN_INPUT = "FOO";
+  private static final String OVERRIDDEN_RESULT = "Size: 3";
+  private static final Key<String> RESULT_KEY = Key.get(String.class, named(RESULT));
+  private static final Key<String> INPUT_KEY = Key.get(String.class, named(PRIVATE_INPUT));
+
+  public void testExposedBindingOverride() throws Exception {
+    Injector inj = Guice.createInjector(
+        Modules.override(new ExampleModule()).with(
+            new AbstractModule() {
+              @Override protected void configure() {
+                bind(RESULT_KEY).toInstance(OVERRIDDEN_RESULT);
+              }
+            }));
+    assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
+  }
+
+  public void testPrivateBindingOverride() throws Exception {
+    Injector inj = Guice.createInjector(
+        Modules.override(new ExampleModule()).with(
+            new AbstractModule() {
+              @Override protected void configure() {
+                bind(INPUT_KEY).toInstance(OVERRIDDEN_INPUT);
+              }
+            }));
+    assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
+  }
+
+  public static class ExampleModule extends PrivateModule {
+    @Provides @Exposed @Named(RESULT)
+    public String provideResult(@Named(PRIVATE_INPUT) String input) {
+      return "Size: " + input.length();
+    }
+
+    @Provides @Named(PRIVATE_INPUT)
+    public String provideInput() {
+      return "Hello World";
+    }
+
+    @Override protected void configure() {
+    }
+  }  
+  
+  public void testEqualsNotCalledByDefaultOnInstance() {
+    final HashEqualsTester a = new HashEqualsTester();
+    a.throwOnEquals = true;
+    Guice.createInjector(Modules.override(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(String.class);
+       bind(HashEqualsTester.class).toInstance(a);
+      }
+    }).with());
+  }
+  
+  public void testEqualsNotCalledByDefaultOnProvider() {
+    final HashEqualsTester a = new HashEqualsTester();
+    a.throwOnEquals = true;
+    Guice.createInjector(Modules.override(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(String.class);
+       bind(Object.class).toProvider(a);
+      }
+    }).with());
+  }
+  
+  public void testHashcodeNeverCalledOnInstance() {
+    final HashEqualsTester a = new HashEqualsTester();
+    a.throwOnHashcode = true;
+    a.equality = "test";
+    
+    final HashEqualsTester b = new HashEqualsTester();
+    b.throwOnHashcode = true;
+    b.equality = "test";
+    Guice.createInjector(Modules.override(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(String.class);
+       bind(HashEqualsTester.class).toInstance(a);
+       bind(HashEqualsTester.class).toInstance(b);
+      }
+    }).with());
+  }
+  
+  public void testHashcodeNeverCalledOnProviderInstance() {
+    final HashEqualsTester a = new HashEqualsTester();
+    a.throwOnHashcode = true;
+    a.equality = "test";
+    
+    final HashEqualsTester b = new HashEqualsTester();
+    b.throwOnHashcode = true;
+    b.equality = "test";
+    Guice.createInjector(Modules.override(new AbstractModule() {
+      @Override
+      protected void configure() {
+       bind(String.class);
+       bind(Object.class).toProvider(a);
+       bind(Object.class).toProvider(b);
+      }
+    }).with());
+  }
+  
+  private static class HashEqualsTester implements Provider<Object> {
+    private String equality;
+    private boolean throwOnEquals;
+    private boolean throwOnHashcode;
+    
+    @Override
+    public boolean equals(Object obj) {
+      if (throwOnEquals) {
+        throw new RuntimeException();
+      } else if (obj instanceof HashEqualsTester) {
+        HashEqualsTester o = (HashEqualsTester)obj;
+        if(o.throwOnEquals) {
+          throw new RuntimeException();
+        }
+        if(equality == null && o.equality == null) {
+          return this == o;
+        } else {
+          return Objects.equal(equality, o.equality);
+        }
+      } else {
+        return false;
+      }
+    }
+    
+    @Override
+    public int hashCode() {
+      if(throwOnHashcode) {
+        throw new RuntimeException();
+      } else {
+        return super.hashCode();
+      }
+    }
+    
+    public Object get() {
+      return new Object();
+    }
+  }
+
+  public void testCorrectStage() {
+    final Stage stage = Stage.PRODUCTION;
+    Module module = Modules.override(new AbstractModule() {
+      @Override
+      protected void configure() {
+        if (currentStage() != Stage.PRODUCTION) {
+          addError("Wronge stage in overridden module:" + currentStage());
+        }
+      }
+    }).with(new AbstractModule() {
+      @Override
+      protected void configure() {
+        if (currentStage() != Stage.PRODUCTION) {
+          addError("Wronge stage in overriding module:" + currentStage());
+        }
+      }
+    });
+    Guice.createInjector(stage, module);
+  }
+
+  public void testOverridesApplyOriginalScanners() {
+    Injector injector =
+        Guice.createInjector(Modules.override(NamedMunger.module()).with(new AbstractModule() {
+      @Override protected void configure() {}
+      @TestProvides @Named("test") String provideString() { return "foo"; }
+    }));
+
+    assertNull(injector.getExistingBinding(Key.get(String.class, named("test"))));
+    Binding<String> binding = injector.getBinding(Key.get(String.class, named("test-munged")));
+    assertEquals("foo", binding.getProvider().get());
+  }
+
+  @Documented @Target(METHOD) @Retention(RUNTIME)
+  private @interface TestProvides {}
+
+  private static class NamedMunger extends ModuleAnnotatedMethodScanner {
+    static Module module() {
+      return new AbstractModule() {
+        @Override protected void configure() {
+          binder().scanModulesForAnnotatedMethods(new NamedMunger());
+        }
+      };
+    }
+
+    @Override
+    public String toString() {
+      return "NamedMunger";
+    }
+
+    @Override
+    public Set<? extends Class<? extends Annotation>> annotationClasses() {
+      return ImmutableSet.of(TestProvides.class);
+    }
+
+    @Override
+    public <T> Key<T> prepareMethod(Binder binder, Annotation annotation, Key<T> key,
+        InjectionPoint injectionPoint) {
+      return Key.get(key.getTypeLiteral(),
+          Names.named(((Named) key.getAnnotation()).value() + "-munged"));
+    }
+  }
+}
diff --git a/core/test/com/google/inject/util/ProvidersTest.java b/core/test/com/google/inject/util/ProvidersTest.java
new file mode 100644
index 0000000..e442c40
--- /dev/null
+++ b/core/test/com/google/inject/util/ProvidersTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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 com.google.inject.util;
+
+import com.google.common.base.Objects;
+import com.google.common.testing.EqualsTester;
+import com.google.inject.Provider;
+
+import junit.framework.TestCase;
+
+import javax.inject.Inject;
+
+/**
+ * Unit tests for {@link Providers}.
+ *
+ * @author Kevin Bourrillion (kevinb9n@gmail.com)
+ */
+public class ProvidersTest extends TestCase {
+
+  public void testOfInstance() {
+    String foo = "foo";
+    Provider<String> p = Providers.of(foo);
+    assertSame(foo, p.get());
+    assertSame(foo, p.get());
+  }
+
+  public void testOfNull() {
+    Provider<String> p = Providers.of(null);
+    assertNull(p.get());
+  }
+  
+  public void testOfEquality() {
+    new EqualsTester()
+        .addEqualityGroup(
+            Providers.of(null),
+            Providers.of(null))
+        .addEqualityGroup(
+            Providers.of("Hello"),
+            Providers.of("Hello"))
+        .testEquals();
+  }
+  
+  public void testGuicifyEquality() {
+    new EqualsTester()
+        .addEqualityGroup(
+            Providers.guicify(new JavaxProvider(10)),
+            Providers.guicify(new JavaxProvider(10)))
+        .addEqualityGroup(
+            Providers.guicify(new JavaxProvider(11)),
+            Providers.guicify(new JavaxProvider(11)))
+        .addEqualityGroup(
+            Providers.guicify(new JavaxProviderWithDependencies()),
+            Providers.guicify(new JavaxProviderWithDependencies()))
+        .testEquals();
+  }
+  
+  private static class JavaxProvider implements javax.inject.Provider<Integer> {
+    private final int value;
+
+    public JavaxProvider(int value) {
+      this.value = value;
+    }
+    
+    public Integer get() {
+      return value;
+    }
+
+    @Override public int hashCode() {
+      return Objects.hashCode(value);
+    }
+
+    @Override public boolean equals(Object obj) {
+      return (obj instanceof JavaxProvider) && (value == ((JavaxProvider) obj).value);
+    }
+  }
+  
+  private static class JavaxProviderWithDependencies implements javax.inject.Provider<Integer> {
+    private int value;
+    
+    @Inject void setValue(int value) {
+      this.value = value;
+    }
+    
+    public Integer get() {
+      return value;
+    }
+
+    @Override public int hashCode() {
+      return 42;
+    }
+
+    @Override public boolean equals(Object obj) {
+      return (obj instanceof JavaxProviderWithDependencies);
+    }
+  }
+}
diff --git a/core/test/com/google/inject/util/TypesTest.java b/core/test/com/google/inject/util/TypesTest.java
new file mode 100644
index 0000000..db015de
--- /dev/null
+++ b/core/test/com/google/inject/util/TypesTest.java
@@ -0,0 +1,215 @@
+/**
+ * Copyright (C) 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.inject.util;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.assertEqualWhenReserialized;
+import static com.google.inject.Asserts.assertEqualsBothWays;
+import static com.google.inject.util.Types.subtypeOf;
+import static com.google.inject.util.Types.supertypeOf;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.MoreTypes;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class TypesTest extends TestCase {
+
+  // generic types for comparison
+  Map<String, Integer> a;
+  Inner<Float, Double> b;
+  List<Set<String>[][]> c;
+  List<String> d;
+  Set<String> e;
+  Outer<String>.Inner f;
+
+  private ParameterizedType mapStringInteger;
+  private ParameterizedType innerFloatDouble;
+  private ParameterizedType listSetStringArray;
+  private ParameterizedType listString;
+  private ParameterizedType setString;
+  private ParameterizedType outerInner;
+  private GenericArrayType setStringArray;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    mapStringInteger = (ParameterizedType) getClass().getDeclaredField("a").getGenericType();
+    innerFloatDouble = (ParameterizedType) getClass().getDeclaredField("b").getGenericType();
+    listSetStringArray = (ParameterizedType) getClass().getDeclaredField("c").getGenericType();
+    listString = (ParameterizedType) getClass().getDeclaredField("d").getGenericType();
+    setString = (ParameterizedType) getClass().getDeclaredField("e").getGenericType();
+    outerInner = (ParameterizedType) getClass().getDeclaredField("f").getGenericType();
+    setStringArray = (GenericArrayType) listSetStringArray.getActualTypeArguments()[0];
+  }
+
+  public void testListSetMap() {
+    assertEqualsBothWays(mapStringInteger, Types.mapOf(String.class, Integer.class));
+    assertEqualsBothWays(listString, Types.listOf(String.class));
+    assertEqualsBothWays(setString, Types.setOf(String.class));
+  }
+
+  public void testDefensiveCopies() {
+    Type[] arguments = new Type[] { String.class, Integer.class };
+    ParameterizedType parameterizedType = Types.newParameterizedType(Map.class, arguments);
+    arguments[0] = null;
+    assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]);
+    parameterizedType.getActualTypeArguments()[1] = null;
+    assertEquals(Integer.class, parameterizedType.getActualTypeArguments()[1]);
+  }
+
+  public void testTypeWithOwnerType() {
+    ParameterizedType actual = Types.newParameterizedTypeWithOwner(
+        TypesTest.class, Inner.class, Float.class, Double.class);
+    assertEquals(TypesTest.class, actual.getOwnerType());
+    assertEqualsBothWays(innerFloatDouble, actual);
+    // The JDK prints this out as:
+    //     com.google.inject.util.TypesTest.com.google.inject.util.TypesTest$Inner<java.lang.Float, java.lang.Double>
+    // and we think that's wrong, so the assertEquals comparison is worthless. :-(
+//    assertEquals(innerFloatDouble.toString(), actual.toString());
+    
+    // We think the correct comparison is:
+    assertEquals("com.google.inject.util.TypesTest$Inner<java.lang.Float, java.lang.Double>", actual.toString());
+  }
+
+  public void testTypeParametersMustNotBePrimitives() {
+    try {
+      Types.newParameterizedType(Map.class, String.class, int.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+      assertContains(expected.getMessage(),
+          "Primitive types are not allowed in type parameters: int");
+    }
+  }
+
+  public List<? extends CharSequence> wildcardExtends;
+  public List<? super CharSequence> wildcardSuper;
+  public List<?> wildcardObject;
+
+  public void testWildcardTypes() throws NoSuchFieldException, IOException {
+    assertEqualsBothWays(getWildcard("wildcardSuper"), supertypeOf(CharSequence.class));
+    assertEqualsBothWays(getWildcard("wildcardExtends"), subtypeOf(CharSequence.class));
+    assertEqualsBothWays(getWildcard("wildcardObject"), subtypeOf(Object.class));
+
+    assertEquals("? super java.lang.CharSequence", supertypeOf(CharSequence.class).toString());
+    assertEquals("? extends java.lang.CharSequence", subtypeOf(CharSequence.class).toString());
+    assertEquals("?", subtypeOf(Object.class).toString());
+
+    assertEqualWhenReserialized(supertypeOf(CharSequence.class));
+    assertEqualWhenReserialized(subtypeOf(CharSequence.class));
+  }
+  
+  public void testWildcardBoundsMustNotBePrimitives() {
+    try {
+      supertypeOf(int.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+      assertContains(expected.getMessage(),
+          "Primitive types are not allowed in wildcard bounds: int");
+    }
+
+    try {
+      subtypeOf(int.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+      assertContains(expected.getMessage(),
+          "Primitive types are not allowed in wildcard bounds: int");
+    }
+  }
+
+  private WildcardType getWildcard(String fieldName) throws NoSuchFieldException {
+    ParameterizedType type = (ParameterizedType) getClass().getField(fieldName).getGenericType();
+    return (WildcardType) type.getActualTypeArguments()[0];
+  }
+
+  public void testEqualsAndHashcode() {
+    ParameterizedType parameterizedType
+        = Types.newParameterizedType(Map.class, String.class, Integer.class);
+    assertEqualsBothWays(mapStringInteger, parameterizedType);
+    assertEquals(mapStringInteger.toString(), parameterizedType.toString());
+
+    GenericArrayType genericArrayType = Types.arrayOf(Types.arrayOf(
+        Types.newParameterizedType(Set.class, String.class)));
+    assertEqualsBothWays(setStringArray, genericArrayType);
+    assertEquals(setStringArray.toString(), genericArrayType.toString());
+  }
+
+  public void testToString() {
+    Assert.assertEquals("java.lang.String", MoreTypes.typeToString(String.class));
+    assertEquals("java.util.Set<java.lang.String>[][]", MoreTypes.typeToString(setStringArray));
+    assertEquals("java.util.Map<java.lang.String, java.lang.Integer>",
+        MoreTypes.typeToString(mapStringInteger));
+    assertEquals("java.util.List<java.util.Set<java.lang.String>[][]>",
+        MoreTypes.typeToString(listSetStringArray));
+    assertEquals(innerFloatDouble.toString(),
+        MoreTypes.typeToString(innerFloatDouble));
+  }
+
+  static class Owning<A> {}
+
+  /**
+   * Ensure that owning types are required when necessary, and forbidden
+   * otherwise.
+   */
+  public void testCanonicalizeRequiresOwnerTypes() {
+    try {
+      Types.newParameterizedType(Owning.class, String.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+      assertContains(expected.getMessage(),
+          "No owner type for enclosed " + Owning.class);
+    }
+
+    try {
+      Types.newParameterizedTypeWithOwner(Object.class, Set.class, String.class);
+    } catch (IllegalArgumentException expected) {
+      assertContains(expected.getMessage(),
+          "Owner type for unenclosed " + Set.class);
+    }
+  }
+
+  @SuppressWarnings("UnusedDeclaration")
+  class Inner<T1, T2> {}
+  
+  public void testInnerParameterizedEvenWithZeroArgs() {
+    TypeLiteral<Outer<String>.Inner> type = new TypeLiteral<Outer<String>.Inner>() {};
+    assertEqualsBothWays(outerInner, type.getType());
+
+    ParameterizedType parameterizedType = (ParameterizedType) type.getType();
+    assertEquals(0, parameterizedType.getActualTypeArguments().length);
+    assertEquals(new TypeLiteral<Outer<String>>() {}.getType(), parameterizedType.getOwnerType());
+    assertEquals(Outer.Inner.class, parameterizedType.getRawType());
+  }
+
+  static class Outer<T> {
+    class Inner {}
+  }
+}
diff --git a/core/test/com/googlecode/guice/BytecodeGenTest.java b/core/test/com/googlecode/guice/BytecodeGenTest.java
new file mode 100644
index 0000000..de4d560
--- /dev/null
+++ b/core/test/com/googlecode/guice/BytecodeGenTest.java
@@ -0,0 +1,328 @@
+/**
+ * Copyright (C) 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.googlecode.guice;
+
+import static com.google.inject.matcher.Matchers.any;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.googlecode.guice.PackageVisibilityTestModule.PublicUserOfPackagePrivate;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.io.File;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * This test is in a separate package so we can test package-level visibility
+ * with confidence.
+ *
+ * @author mcculls@gmail.com (Stuart McCulloch)
+ */
+public class BytecodeGenTest extends TestCase {
+
+  private final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+
+  private final Module interceptorModule = new AbstractModule() {
+    protected void configure() {
+      bindInterceptor(any(), any(), new MethodInterceptor() {
+        public Object invoke(MethodInvocation chain)
+            throws Throwable {
+          return chain.proceed() + " WORLD";
+        }
+      });
+    }
+  };
+
+  private final Module noopInterceptorModule = new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(any(), any(), new MethodInterceptor() {
+          public Object invoke(MethodInvocation chain)
+              throws Throwable {
+            return chain.proceed();
+          }
+        });
+      }
+    };
+
+  public void testPackageVisibility() {
+    Injector injector = Guice.createInjector(new PackageVisibilityTestModule());
+    injector.getInstance(PublicUserOfPackagePrivate.class); // This must pass.
+  }
+
+  public void testInterceptedPackageVisibility() {
+    Injector injector = Guice.createInjector(interceptorModule, new PackageVisibilityTestModule());
+    injector.getInstance(PublicUserOfPackagePrivate.class); // This must pass.
+  }
+
+  public void testEnhancerNaming() {
+    Injector injector = Guice.createInjector(interceptorModule, new PackageVisibilityTestModule());
+    PublicUserOfPackagePrivate pupp = injector.getInstance(PublicUserOfPackagePrivate.class);
+    assertTrue(pupp.getClass().getName().startsWith(
+        PublicUserOfPackagePrivate.class.getName() + "$$EnhancerByGuice$$"));
+  }
+
+  // TODO(sameb): Figure out how to test FastClass naming tests.
+
+  /**
+   * Custom URL classloader with basic visibility rules
+   */
+  static class TestVisibilityClassLoader
+      extends URLClassLoader {
+
+    boolean hideInternals;
+
+    public TestVisibilityClassLoader(boolean hideInternals) {
+      super(new URL[0]);
+
+      this.hideInternals = hideInternals;
+
+      final String[] classpath = System.getProperty("java.class.path").split(File.pathSeparator);
+      for (final String element : classpath) {
+        try {
+          // is it a remote/local URL?
+          addURL(new URL(element));
+        } catch (final MalformedURLException e1) {
+          try {
+            // nope - perhaps it's a filename?
+            addURL(new File(element).toURI().toURL());
+          } catch (final MalformedURLException e2) {
+            throw new RuntimeException(e1);
+          }
+        }
+      }
+    }
+
+    /**
+     * Classic parent-delegating classloaders are meant to override findClass.
+     * However, non-delegating classloaders (as used in OSGi) instead override
+     * loadClass to provide support for "class-space" separation.
+     */
+    @Override
+    protected Class<?> loadClass(final String name, final boolean resolve)
+        throws ClassNotFoundException {
+
+      synchronized (this) {
+        // check our local cache to avoid duplicates
+        final Class<?> clazz = findLoadedClass(name);
+        if (clazz != null) {
+          return clazz;
+        }
+      }
+
+      if (name.startsWith("java.")) {
+
+        // standard bootdelegation of java.*
+        return super.loadClass(name, resolve);
+
+      } else if (!name.contains(".internal.") && !name.contains(".cglib.")) {
+
+        /*
+         * load public and test classes directly from the classpath - we don't
+         * delegate to our parent because then the loaded classes would also be
+         * able to see private internal Guice classes, as they are also loaded
+         * by the parent classloader.
+         */
+        final Class<?> clazz = findClass(name);
+        if (resolve) {
+          resolveClass(clazz);
+        }
+        return clazz;
+      }
+
+      // hide internal non-test classes
+      if (hideInternals) {
+        throw new ClassNotFoundException();
+      }
+      return super.loadClass(name, resolve);
+    }
+  }
+
+  /** as loaded by another class loader */
+  private Class<ProxyTest> proxyTestClass;
+  private Class<ProxyTestImpl> realClass;
+  private Module testModule;
+
+  @SuppressWarnings("unchecked")
+  protected void setUp() throws Exception {
+    super.setUp();
+
+    ClassLoader testClassLoader = new TestVisibilityClassLoader(true);
+    proxyTestClass = (Class<ProxyTest>) testClassLoader.loadClass(ProxyTest.class.getName());
+    realClass = (Class<ProxyTestImpl>) testClassLoader.loadClass(ProxyTestImpl.class.getName());
+
+    testModule = new AbstractModule() {
+      public void configure() {
+        bind(proxyTestClass).to(realClass);
+      }
+    };
+  }
+
+  interface ProxyTest {
+    String sayHello();
+  }
+
+  /**
+   * Note: this class must be marked as public or protected so that the Guice
+   * custom classloader will intercept it. Private and implementation classes
+   * are not intercepted by the custom classloader.
+   * 
+   * @see com.google.inject.internal.BytecodeGen.Visibility
+   */
+  public static class ProxyTestImpl implements ProxyTest {
+
+    static {
+      //System.out.println(ProxyTestImpl.class.getClassLoader());
+    }
+
+    public String sayHello() {
+      return "HELLO";
+    }
+  }
+
+  public void testProxyClassLoading() throws Exception {
+    Object testObject = Guice.createInjector(interceptorModule, testModule)
+        .getInstance(proxyTestClass);
+
+    // verify method interception still works
+    Method m = realClass.getMethod("sayHello");
+    assertEquals("HELLO WORLD", m.invoke(testObject));
+  }
+
+  public void testSystemClassLoaderIsUsedIfProxiedClassUsesIt() {
+    ProxyTest testProxy = Guice.createInjector(interceptorModule, new Module() {
+      public void configure(Binder binder) {
+        binder.bind(ProxyTest.class).to(ProxyTestImpl.class);
+      }
+    }).getInstance(ProxyTest.class);
+
+    if (ProxyTest.class.getClassLoader() == systemClassLoader) {
+      assertSame(testProxy.getClass().getClassLoader(), systemClassLoader);
+    } else {
+      assertNotSame(testProxy.getClass().getClassLoader(), systemClassLoader);
+    }
+  }
+
+  public void testProxyClassUnloading() {
+    Object testObject = Guice.createInjector(interceptorModule, testModule)
+        .getInstance(proxyTestClass);
+    assertNotNull(testObject.getClass().getClassLoader());
+    assertNotSame(testObject.getClass().getClassLoader(), systemClassLoader);
+
+    // take a weak reference to the generated proxy class
+    Reference<Class<?>> clazzRef = new WeakReference<Class<?>>(testObject.getClass());
+
+    assertNotNull(clazzRef.get());
+
+    // null the proxy
+    testObject = null;
+
+    /*
+     * this should be enough to queue the weak reference
+     * unless something is holding onto it accidentally.
+     */
+    final int MAX_COUNT = 100;
+    String[] buf;
+    System.gc();
+    //TODO(cgruber): Use com.google.common.testing.GcFinalization and a countdown latch to un-flake.
+    for (int count = 0 ; clazzRef.get() != null ; count++) {
+      buf = new String[8 * 1024 * 1024];
+      buf = null;
+      System.gc();
+      assertTrue("Timeout waiting for class to be unloaded.  This may be a flaky result.",
+          count <= MAX_COUNT);
+    }
+
+    // This test could be somewhat flaky when the GC isn't working.
+    // If it fails, run the test again to make sure it's failing reliably.
+    assertNull("Proxy class was not unloaded.", clazzRef.get());
+  }
+
+  public void testProxyingPackagePrivateMethods() {
+    Injector injector = Guice.createInjector(interceptorModule);
+    assertEquals("HI WORLD", injector.getInstance(PackageClassPackageMethod.class).sayHi());
+    assertEquals("HI WORLD", injector.getInstance(PublicClassPackageMethod.class).sayHi());
+    assertEquals("HI WORLD", injector.getInstance(ProtectedClassProtectedMethod.class).sayHi());
+  }
+
+  static class PackageClassPackageMethod {
+    String sayHi() {
+      return "HI";
+    }
+  }
+
+  public static class PublicClassPackageMethod {
+    String sayHi() {
+      return "HI";
+    }
+  }
+
+  protected static class ProtectedClassProtectedMethod {
+    protected String sayHi() {
+      return "HI";
+    }
+  }
+
+  static class Hidden {
+  }
+
+  public static class HiddenMethodReturn {
+    public Hidden method() {
+      return new Hidden();
+    }
+  }
+
+  public static class HiddenMethodParameter {
+    public void method(Hidden h) {
+    }
+  }
+
+  public void testClassLoaderBridging() throws Exception {
+    ClassLoader testClassLoader = new TestVisibilityClassLoader(false);
+
+    Class hiddenMethodReturnClass = testClassLoader.loadClass(HiddenMethodReturn.class.getName());
+    Class hiddenMethodParameterClass = testClassLoader.loadClass(HiddenMethodParameter.class.getName());
+
+    Injector injector = Guice.createInjector(noopInterceptorModule);
+
+    Class hiddenClass = testClassLoader.loadClass(Hidden.class.getName());
+    Constructor ctor = hiddenClass.getDeclaredConstructor();
+
+    ctor.setAccessible(true);
+
+    // don't use bridging for proxies with private parameters
+    Object o1 = injector.getInstance(hiddenMethodParameterClass);
+    o1.getClass().getDeclaredMethod("method", hiddenClass).invoke(o1, ctor.newInstance());
+
+    // don't use bridging for proxies with private return types
+    Object o2 = injector.getInstance(hiddenMethodReturnClass);
+    o2.getClass().getDeclaredMethod("method").invoke(o2);
+  }
+}
diff --git a/core/test/com/googlecode/guice/GuiceTck.java b/core/test/com/googlecode/guice/GuiceTck.java
new file mode 100644
index 0000000..5616fd7
--- /dev/null
+++ b/core/test/com/googlecode/guice/GuiceTck.java
@@ -0,0 +1,60 @@
+/**
+ * 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 com.googlecode.guice;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Provides;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+import org.atinject.tck.Tck;
+import org.atinject.tck.auto.Car;
+import org.atinject.tck.auto.Convertible;
+import org.atinject.tck.auto.Drivers;
+import org.atinject.tck.auto.DriversSeat;
+import org.atinject.tck.auto.Engine;
+import org.atinject.tck.auto.FuelTank;
+import org.atinject.tck.auto.Seat;
+import org.atinject.tck.auto.Tire;
+import org.atinject.tck.auto.V8Engine;
+import org.atinject.tck.auto.accessories.Cupholder;
+import org.atinject.tck.auto.accessories.SpareTire;
+
+import javax.inject.Named;
+
+public class GuiceTck extends TestCase {
+
+  public static Test suite() {
+    return Tck.testsFor(Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Car.class).to(Convertible.class);
+        bind(Seat.class).annotatedWith(Drivers.class).to(DriversSeat.class);
+        bind(Engine.class).to(V8Engine.class);
+        bind(Cupholder.class);
+        bind(Tire.class);
+        bind(FuelTank.class);
+        requestStaticInjection(Convertible.class, SpareTire.class);
+      }
+
+      @Provides @Named("spare") Tire provideSpareTire(SpareTire spare) {
+        return spare;
+      }
+    }).getInstance(Car.class), true, true);
+  }
+}
diff --git a/core/test/com/googlecode/guice/Jsr330Test.java b/core/test/com/googlecode/guice/Jsr330Test.java
new file mode 100644
index 0000000..57cd6e0
--- /dev/null
+++ b/core/test/com/googlecode/guice/Jsr330Test.java
@@ -0,0 +1,475 @@
+/**
+ * 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 com.googlecode.guice;
+
+import static com.google.inject.Asserts.assertContains;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Scope;
+import com.google.inject.Scopes;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Qualifier;
+import javax.inject.Singleton;
+
+public class Jsr330Test extends TestCase {
+
+  private final B b = new B();
+  private final C c = new C();
+  private final D d = new D();
+  private final E e = new E();
+
+  @Override protected void setUp() throws Exception {
+    J.nextInstanceId = 0;
+    K.nextInstanceId = 0;
+  }
+
+  public void testInject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(B.class).toInstance(b);
+        bind(C.class).toInstance(c);
+        bind(D.class).toInstance(d);
+        bind(E.class).toInstance(e);
+        bind(A.class);
+      }
+    });
+
+    A a = injector.getInstance(A.class);
+    assertSame(b, a.b);
+    assertSame(c, a.c);
+    assertSame(d, a.d);
+    assertSame(e, a.e);
+  }
+
+  public void testQualifiedInject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(B.class).annotatedWith(Names.named("jodie")).toInstance(b);
+        bind(C.class).annotatedWith(Red.class).toInstance(c);
+        bind(D.class).annotatedWith(RED).toInstance(d);
+        bind(E.class).annotatedWith(Names.named("jesse")).toInstance(e);
+        bind(F.class);
+      }
+    });
+
+    F f = injector.getInstance(F.class);
+    assertSame(b, f.b);
+    assertSame(c, f.c);
+    assertSame(d, f.d);
+    assertSame(e, f.e);
+  }
+
+  public void testProviderInject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(B.class).annotatedWith(Names.named("jodie")).toInstance(b);
+        bind(C.class).toInstance(c);
+        bind(D.class).annotatedWith(RED).toInstance(d);
+        bind(E.class).toInstance(e);
+        bind(G.class);
+      }
+    });
+
+    G g = injector.getInstance(G.class);
+    assertSame(b, g.bProvider.get());
+    assertSame(c, g.cProvider.get());
+    assertSame(d, g.dProvider.get());
+    assertSame(e, g.eProvider.get());
+  }
+
+  public void testScopeAnnotation() {
+    final TestScope scope = new TestScope();
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(B.class).in(scope);
+        bind(C.class).in(TestScoped.class);
+        bindScope(TestScoped.class, scope);
+      }
+    });
+
+    B b = injector.getInstance(B.class);
+    assertSame(b, injector.getInstance(B.class));
+    assertSame(b, injector.getInstance(B.class));
+
+    C c = injector.getInstance(C.class);
+    assertSame(c, injector.getInstance(C.class));
+    assertSame(c, injector.getInstance(C.class));
+
+    H h = injector.getInstance(H.class);
+    assertSame(h, injector.getInstance(H.class));
+    assertSame(h, injector.getInstance(H.class));
+
+    scope.reset();
+
+    assertNotSame(b, injector.getInstance(B.class));
+    assertNotSame(c, injector.getInstance(C.class));
+    assertNotSame(h, injector.getInstance(H.class));
+  }
+  
+  public void testSingleton() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(B.class).in(Singleton.class);
+      }
+    });
+
+    B b = injector.getInstance(B.class);
+    assertSame(b, injector.getInstance(B.class));
+    assertSame(b, injector.getInstance(B.class));
+
+    J j = injector.getInstance(J.class);
+    assertSame(j, injector.getInstance(J.class));
+    assertSame(j, injector.getInstance(J.class));
+  }
+
+  public void testEagerSingleton() {
+    Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
+      protected void configure() {
+        bind(J.class);
+        bind(K.class).in(Singleton.class);
+      }
+    });
+
+    assertEquals(1, J.nextInstanceId);
+    assertEquals(1, K.nextInstanceId);
+  }
+  
+  public void testScopesIsSingleton() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(J.class);
+        bind(K.class).in(Singleton.class);
+      }
+    });
+
+    assertTrue(Scopes.isSingleton(injector.getBinding(J.class)));
+    assertTrue(Scopes.isSingleton(injector.getBinding(K.class)));
+  }
+
+  public void testInjectingFinalFieldsIsForbidden() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(L.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Injected field " + L.class.getName() + ".b cannot be final.");
+    }
+  }
+
+  public void testInjectingAbstractMethodsIsForbidden() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(M.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Injected method " + AbstractM.class.getName() + ".setB() cannot be abstract.");
+    }
+  }
+
+  public void testInjectingMethodsWithTypeParametersIsForbidden() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(N.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "1) Injected method " + N.class.getName()
+          + ".setB() cannot declare type parameters of its own.");
+    }
+  }
+
+  public void testInjectingMethodsWithNonVoidReturnTypes() {
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(P.class);
+      }
+    });
+  }
+
+  /**
+   * This test verifies that we can compile bindings to provider instances
+   * whose compile-time type implements javax.inject.Provider but not
+   * com.google.inject.Provider. For binary compatibility, we don't (and won't)
+   * support binding to instances of javax.inject.Provider.
+   */
+  public void testBindProviderClass() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(B.class).toProvider(BProvider.class);
+        bind(B.class).annotatedWith(Names.named("1")).toProvider(BProvider.class);
+        bind(B.class).annotatedWith(Names.named("2")).toProvider(Key.get(BProvider.class));
+        bind(B.class).annotatedWith(Names.named("3")).toProvider(TypeLiteral.get(BProvider.class));
+      }
+    });
+    
+    injector.getInstance(Key.get(B.class));
+    injector.getInstance(Key.get(B.class, Names.named("1")));
+    injector.getInstance(Key.get(B.class, Names.named("2")));
+    injector.getInstance(Key.get(B.class, Names.named("3")));
+  }
+
+  public void testGuicify330Provider() {
+    Provider<String> jsr330Provider = new Provider<String>() {
+      public String get() {
+        return "A";
+      }
+
+      @Override public String toString() {
+        return "jsr330Provider";
+      }
+    };
+
+    com.google.inject.Provider<String> guicified = Providers.guicify(jsr330Provider);
+    assertEquals("guicified(jsr330Provider)", guicified.toString());
+    assertEquals("A", guicified.get());
+
+    // when you guicify the Guice-friendly, it's a no-op
+    assertSame(guicified, Providers.guicify(guicified));
+    
+    assertFalse(guicified instanceof HasDependencies);
+  }
+  
+  public void testGuicifyWithDependencies() {
+    Provider<String> jsr330Provider = new Provider<String>() {
+      @Inject double d;
+      int i;
+      @Inject void injectMe(int i) {
+        this.i = i;
+      }
+      
+      public String get() {
+        return  d + "-" + i;
+      }
+    };
+    
+    final com.google.inject.Provider<String> guicified =
+        Providers.guicify(jsr330Provider);
+    assertTrue(guicified instanceof HasDependencies);
+    Set<Dependency<?>> actual = ((HasDependencies)guicified).getDependencies();
+    validateDependencies(actual, jsr330Provider.getClass());
+    
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toProvider(guicified);
+        bind(int.class).toInstance(1);
+        bind(double.class).toInstance(2.0d);
+      }
+    });
+    
+    Binding<String> binding = injector.getBinding(String.class);
+    assertEquals("2.0-1", binding.getProvider().get());
+    validateDependencies(actual, jsr330Provider.getClass());
+  }
+  
+  private void validateDependencies(Set<Dependency<?>> actual, Class<?> owner) {
+    assertEquals(actual.toString(), 2, actual.size());
+    Dependency<?> dDep = null;
+    Dependency<?> iDep = null;
+    for(Dependency<?> dep : actual) {
+      if(dep.getKey().equals(Key.get(Double.class))) {
+        dDep = dep;
+      } else if(dep.getKey().equals(Key.get(Integer.class))) {
+        iDep = dep;
+      }
+    }
+    assertNotNull(dDep);
+    assertNotNull(iDep);
+    assertEquals(TypeLiteral.get(owner), dDep.getInjectionPoint().getDeclaringType());
+    assertEquals("d", dDep.getInjectionPoint().getMember().getName());
+    assertEquals(-1, dDep.getParameterIndex());
+    
+    assertEquals(TypeLiteral.get(owner), iDep.getInjectionPoint().getDeclaringType());
+    assertEquals("injectMe", iDep.getInjectionPoint().getMember().getName());
+    assertEquals(0, iDep.getParameterIndex());
+  }
+
+  static class A {
+    final B b;
+    @Inject C c;
+    D d;
+    E e;
+
+    @Inject A(B b) {
+      this.b = b;
+    }
+
+    @Inject void injectD(D d, E e) {
+      this.d = d;
+      this.e = e;
+    }
+  }
+
+  static class B {}
+  static class C {}
+  static class D {}
+  static class E {}
+
+  static class F {
+    final B b;
+    @Inject @Red C c;
+    D d;
+    E e;
+
+    @Inject F(@Named("jodie") B b) {
+      this.b = b;
+    }
+
+    @Inject void injectD(@Red D d, @Named("jesse") E e) {
+      this.d = d;
+      this.e = e;
+    }
+  }
+
+  @Qualifier @Retention(RUNTIME)
+  @interface Red {}
+
+  public static final Red RED = new Red() {
+    public Class<? extends Annotation> annotationType() {
+      return Red.class;
+    }
+
+    @Override public boolean equals(Object obj) {
+      return obj instanceof Red;
+    }
+
+    @Override public int hashCode() {
+      return 0;
+    }
+  };
+
+  static class G {
+    final Provider<B> bProvider;
+    @Inject Provider<C> cProvider;
+    Provider<D> dProvider;
+    Provider<E> eProvider;
+
+    @Inject G(@Named("jodie") Provider<B> bProvider) {
+      this.bProvider = bProvider;
+    }
+
+    @Inject void injectD(@Red Provider<D> dProvider, Provider<E> eProvider) {
+      this.dProvider = dProvider;
+      this.eProvider = eProvider;
+    }
+  }
+
+  @javax.inject.Scope @Retention(RUNTIME)
+  @interface TestScoped {}
+
+  static class TestScope implements Scope {
+    private int now = 0;
+
+    public <T> com.google.inject.Provider<T> scope(Key<T> key,
+        final com.google.inject.Provider<T> unscoped) {
+      return new com.google.inject.Provider<T>() {
+        private T value;
+        private int snapshotTime = -1;
+
+        public T get() {
+          if (snapshotTime != now) {
+            value = unscoped.get();
+            snapshotTime = now;
+          }
+          return value;
+        }
+      };
+    }
+
+    public void reset() {
+      now++;
+    }
+  }
+
+  @TestScoped
+  static class H {}
+
+  @Singleton
+  static class J {
+    static int nextInstanceId = 0;
+    int instanceId = nextInstanceId++;
+  }
+
+  static class K {
+    static int nextInstanceId = 0;
+    int instanceId = nextInstanceId++;
+  }
+
+  static class L {
+    @SuppressWarnings("InjectJavaxInjectOnFinalField")
+    @Inject
+    final B b = null;
+  }
+
+  static abstract class AbstractM {
+    @SuppressWarnings("InjectJavaxInjectOnAbstractMethod")
+    @Inject
+    abstract void setB(B b);
+  }
+
+  static class M extends AbstractM {
+    void setB(B b) {}
+  }
+
+  static class N {
+    @Inject <T> void setB(B b) {}
+  }
+
+  static class P {
+    @Inject B setB(B b) {
+      return b;
+    }
+  }
+
+  static class BProvider implements Provider<B> {
+    public B get() {
+      return new B();
+    }
+  }
+}
diff --git a/core/test/com/googlecode/guice/OSGiContainerTest.java b/core/test/com/googlecode/guice/OSGiContainerTest.java
new file mode 100644
index 0000000..b91975f
--- /dev/null
+++ b/core/test/com/googlecode/guice/OSGiContainerTest.java
@@ -0,0 +1,162 @@
+/**
+ * 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 com.googlecode.guice;
+
+
+import aQute.bnd.main.bnd;
+
+import com.googlecode.guice.bundle.OSGiTestActivator;
+
+import junit.framework.TestCase;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.Properties;
+
+import javax.imageio.spi.ServiceRegistry;
+
+/**
+ * Run various tests inside one or more OSGi containers.
+ *
+ * @author mcculls@gmail.com (Stuart McCulloch)
+ */
+public class OSGiContainerTest
+    extends TestCase {
+
+  // build properties passed from Ant
+  static final String VERSION = System.getProperty("version", "snapshot");
+  static final String BUILD_DIR = System.getProperty("build.dir", "build");
+
+  static final String BUILD_DIST_DIR = BUILD_DIR + "/dist";
+  static final String BUILD_TEST_DIR = BUILD_DIR + "/test";
+
+  static final String GUICE_JAR = BUILD_DIST_DIR + "/guice-" + VERSION + ".jar";
+
+/*if[AOP]*/
+  static final String AOPALLIANCE_JAR = System.getProperty("aopalliance.jar", "lib/aopalliance.jar");
+/*end[AOP]*/
+  static final String JAVAX_INJECT_JAR = System.getProperty("javax.inject.jar", "lib/javax.inject.jar");
+  static final String GUAVA_JAR = System.getProperty("guava.jar", "lib/guava-16.0.1.jar");
+
+  // dynamically build test bundles
+  @Override protected void setUp()
+      throws Exception {
+
+    // verify properties
+    assertTrue(failMsg(), new File(BUILD_DIR).isDirectory());
+    assertTrue(failMsg(), new File(GUICE_JAR).isFile());
+
+/*if[AOP]*/
+    assertTrue(failMsg(), new File(AOPALLIANCE_JAR).isFile());
+/*end[AOP]*/
+    assertTrue(failMsg(), new File(JAVAX_INJECT_JAR).isFile());
+    assertTrue(failMsg(), new File(GUAVA_JAR).isFile());
+
+    Properties instructions = new Properties();
+
+/*if[AOP]*/
+    // aopalliance is an API bundle --> export the full API
+    instructions.setProperty("Export-Package", "org.aopalliance.*");
+    buildBundle("aopalliance", instructions, AOPALLIANCE_JAR);
+    instructions.clear();
+/*end[AOP]*/
+
+    // javax.inject is an API bundle --> export the full API
+    instructions.setProperty("Export-Package", "javax.inject.*");
+    buildBundle("javax.inject", instructions, JAVAX_INJECT_JAR);
+    instructions.clear();
+
+    // early versions of guava did not ship with OSGi metadata
+    instructions.setProperty("Export-Package", "com.google.common.*");
+    instructions.setProperty("Import-Package", "*;resolution:=optional");
+    buildBundle("guava", instructions, GUAVA_JAR);
+    instructions.clear();
+
+    // strict imports to make sure test bundle only has access to these packages
+    instructions.setProperty("Import-Package", "org.osgi.framework,"
+/*if[AOP]*/
+        + "org.aopalliance.intercept,"
+/*end[AOP]*/
+        + "com.google.inject(|.binder|.matcher|.name)");
+
+    // test bundle should only contain the local test classes, nothing else
+    instructions.setProperty("Bundle-Activator", OSGiTestActivator.class.getName());
+    instructions.setProperty("Private-Package", OSGiTestActivator.class.getPackage().getName());
+    buildBundle("osgitests", instructions, BUILD_TEST_DIR);
+    instructions.clear();
+  }
+
+  // build an OSGi bundle at runtime
+  private static void buildBundle(String name, Properties instructions, String classpath)
+      throws IOException {
+
+    // write BND instructions to temporary test directory
+    String bndFileName = BUILD_TEST_DIR + '/' + name + ".bnd";
+    OutputStream os = new BufferedOutputStream(new FileOutputStream(bndFileName));
+    instructions.store(os, "BND instructions");
+    os.close();
+
+    // assemble bundle, use -failok switch to avoid early exit
+    bnd.main(new String[]{"-failok", "build", "-classpath", classpath, bndFileName});
+  }
+
+  private String failMsg() {
+    return "This test may fail if it is not run from ant, or if it is not run after ant has "
+         + "compiled & built jars. This is because the test is validating that the Guice jar "
+         + "is properly setup to load in an OSGi container";
+  }
+
+  //This test may fail if it is not run from ant, or if it is not run after ant has
+  //compiled & built jars. This is because the test is validating that the Guice jar
+  //is properly setup to load in an OSGi container
+  public void testGuiceWorksInOSGiContainer()
+      throws Throwable {
+
+    // ask framework to clear cache on startup
+    Properties properties = new Properties();
+    properties.setProperty("org.osgi.framework.storage", BUILD_TEST_DIR + "/bundle.cache");
+    properties.setProperty("org.osgi.framework.storage.clean", "onFirstInit");
+
+    // test each available OSGi framework in turn
+    Iterator<FrameworkFactory> f = ServiceRegistry.lookupProviders(FrameworkFactory.class);
+    while (f.hasNext()) {
+      Framework framework = f.next().newFramework(properties);
+
+      framework.start();
+      BundleContext systemContext = framework.getBundleContext();
+
+      // load all the necessary bundles and start the OSGi test bundle
+/*if[AOP]*/
+      systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/aopalliance.jar");
+/*end[AOP]*/
+      systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/javax.inject.jar");
+      systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/guava.jar");
+      systemContext.installBundle("reference:file:" + GUICE_JAR);
+      systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/osgitests.jar").start();
+
+      framework.stop();
+    }
+  }
+}
diff --git a/core/test/com/googlecode/guice/PackageVisibilityTestModule.java b/core/test/com/googlecode/guice/PackageVisibilityTestModule.java
new file mode 100644
index 0000000..f228684
--- /dev/null
+++ b/core/test/com/googlecode/guice/PackageVisibilityTestModule.java
@@ -0,0 +1,21 @@
+package com.googlecode.guice;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+
+public class PackageVisibilityTestModule extends AbstractModule {
+
+  @Override
+  protected void configure() {
+    bind(PackagePrivateInterface.class).to(PackagePrivateImpl.class);
+  }
+
+  public static class PublicUserOfPackagePrivate {
+    @Inject public PublicUserOfPackagePrivate(PackagePrivateInterface ppi) {}
+    @Inject public void acceptPackagePrivateParameter(PackagePrivateInterface ppi) {}
+  }
+
+  interface PackagePrivateInterface {}
+
+  static class PackagePrivateImpl implements PackagePrivateInterface {}
+}
diff --git a/core/test/com/googlecode/guice/bundle/OSGiTestActivator.java b/core/test/com/googlecode/guice/bundle/OSGiTestActivator.java
new file mode 100644
index 0000000..67caee5
--- /dev/null
+++ b/core/test/com/googlecode/guice/bundle/OSGiTestActivator.java
@@ -0,0 +1,511 @@
+/**
+ * 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 com.googlecode.guice.bundle;
+
+import static com.google.inject.name.Names.named;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.matcher.AbstractMatcher;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Random;
+
+/**
+ * Test Guice from inside an OSGi bundle activator.
+ * 
+ * @author mcculls@gmail.com (Stuart McCulloch)
+ */
+@SuppressWarnings("unused") public class OSGiTestActivator
+    implements BundleActivator {
+
+  // varying visibilities to test our code-generation support
+
+  public static class Undefined {}
+
+  public interface A {}
+
+  protected interface B {}
+
+  interface C {}
+
+  private interface D {}
+
+  public static class AA
+      implements A {
+
+    public AA() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  protected static class AB
+      implements A {
+
+    public AB() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  static class AC
+      implements A {
+
+    public AC() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  private static class AD
+      implements A {
+
+    public AD() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  public static class BA
+      implements B {
+
+    protected BA() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  protected static class BB
+      implements B {
+
+    protected BB() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  static class BC
+      implements B {
+
+    protected BC() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  private static class BD
+      implements B {
+
+    protected BD() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  public static class CA
+      implements C {
+
+    CA() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  protected static class CB
+      implements C {
+
+    CB() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  static class CC
+      implements C {
+
+    CC() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  private static class CD
+      implements C {
+
+    CD() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  public static class DA
+      implements D {
+
+    @Inject private DA() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  protected static class DB
+      implements D {
+
+    @Inject private DB() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  static class DC
+      implements D {
+
+    @Inject private DC() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  private static class DD
+      implements D {
+
+    private DD() {}
+
+    @Inject public void setA(Undefined undefined) {}
+
+    @Inject protected void setB(Undefined undefined) {}
+
+    @Inject void setC(Undefined undefined) {}
+
+    @Inject private void setD(Undefined undefined) {}
+
+    @Inject public Undefined a;
+
+    @Inject protected Undefined b;
+
+    @Inject Undefined c;
+
+    @Inject private Undefined d;
+  }
+
+  enum Visibility {
+    PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE
+  }
+
+  static final Class<?>[] TEST_CLAZZES = {A.class, B.class, C.class, D.class};
+
+  // registers all the class combinations
+  static class TestModule
+      extends AbstractModule {
+
+    final Bundle bundle;
+
+    TestModule(Bundle bundle) {
+      this.bundle = bundle;
+    }
+
+    @Override @SuppressWarnings("unchecked") protected void configure() {
+      for (Class<?> api : TEST_CLAZZES) {
+        for (Visibility visibility : Visibility.values()) {
+          try {
+
+            // this registers: A + PUBLIC -> AA, A + PROTECTED -> AB, etc...
+            String suffix = TEST_CLAZZES[visibility.ordinal()].getSimpleName();
+            Class imp = bundle.loadClass(api.getName() + suffix);
+            bind(api).annotatedWith(named(visibility.name())).to(imp);
+
+          } catch (ClassNotFoundException e) {
+            throw new RuntimeException("Unable to load test class", e);
+          }
+        }
+      }
+    }
+  }
+
+/*if[AOP]*/
+  // applies method-interception to classes with enough visibility
+  static class InterceptorModule
+      extends AbstractModule {
+    @Override protected void configure() {
+      bindInterceptor(new AbstractMatcher<Class<?>>() {
+        public boolean matches(Class<?> clazz) {
+          try {
+
+            // the class and constructor must be visible
+            int clazzModifiers = clazz.getModifiers();
+            int ctorModifiers = clazz.getConstructor().getModifiers();
+            return (clazzModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0
+                && (ctorModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0;
+
+          } catch (NoSuchMethodException e) {
+            return false;
+          }
+        }
+      }, new AbstractMatcher<Method>() {
+        public boolean matches(Method method) {
+
+          // the intercepted method must also be visible
+          int methodModifiers = method.getModifiers();
+          return (methodModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0;
+
+        }
+      }, new org.aopalliance.intercept.MethodInterceptor() {
+        public Object invoke(org.aopalliance.intercept.MethodInvocation mi)
+            throws Throwable {
+
+          return mi.proceed();
+        }
+      });
+    }
+  }
+/*end[AOP]*/
+
+  // called from OSGi when bundle starts
+  public void start(BundleContext context)
+      throws BundleException {
+
+    final Bundle bundle = context.getBundle();
+
+    Injector injector = Guice.createInjector(new TestModule(bundle));
+/*if[AOP]*/
+    Injector aopInjector = Guice.createInjector(new TestModule(bundle), new InterceptorModule());
+/*end[AOP]*/
+
+    // test code-generation support
+    for (Class<?> api : TEST_CLAZZES) {
+      for (Visibility vis : Visibility.values()) {
+        injector.getInstance(Key.get(api, named(vis.name())));
+/*if[AOP]*/
+        aopInjector.getInstance(Key.get(api, named(vis.name())));
+/*end[AOP]*/
+      }
+    }
+
+    // test injection of system class (issue 343)
+    injector.getInstance(Random.class);
+/*if[AOP]*/
+    aopInjector.getInstance(Random.class);
+/*end[AOP]*/
+  }
+
+  // called from OSGi when bundle stops
+  public void stop(BundleContext context) {}
+}
diff --git a/examples/src/example/xml/Contact.java b/examples/src/example/xml/Contact.java
new file mode 100644
index 0000000..160dbdc
--- /dev/null
+++ b/examples/src/example/xml/Contact.java
@@ -0,0 +1,5 @@
+package example.xml;
+
+public class Contact {
+
+}
diff --git a/examples/src/example/xml/Contacts.java b/examples/src/example/xml/Contacts.java
new file mode 100644
index 0000000..1efea32
--- /dev/null
+++ b/examples/src/example/xml/Contacts.java
@@ -0,0 +1,5 @@
+package example.xml;
+
+public interface Contacts {
+  Iterable<Contact> findByName(String name);
+}
diff --git a/examples/src/example/xml/FlashMemory.java b/examples/src/example/xml/FlashMemory.java
new file mode 100644
index 0000000..14294f4
--- /dev/null
+++ b/examples/src/example/xml/FlashMemory.java
@@ -0,0 +1,10 @@
+package example.xml;
+
+import java.util.Collections;
+
+public class FlashMemory implements Contacts {
+
+  public Iterable<Contact> findByName(String name) {
+    return Collections.emptyList();
+  }
+}
diff --git a/examples/src/example/xml/FromFlash.java b/examples/src/example/xml/FromFlash.java
new file mode 100644
index 0000000..def2044
--- /dev/null
+++ b/examples/src/example/xml/FromFlash.java
@@ -0,0 +1,7 @@
+package example.xml;
+
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.*;
+
+@Retention(RUNTIME)
+public @interface FromFlash {}
\ No newline at end of file
diff --git a/examples/src/example/xml/FromSim.java b/examples/src/example/xml/FromSim.java
new file mode 100644
index 0000000..47ed416
--- /dev/null
+++ b/examples/src/example/xml/FromSim.java
@@ -0,0 +1,7 @@
+package example.xml;
+
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.*;
+
+@Retention(RUNTIME)
+public @interface FromSim {}
diff --git a/examples/src/example/xml/Main.java b/examples/src/example/xml/Main.java
new file mode 100644
index 0000000..6983dec
--- /dev/null
+++ b/examples/src/example/xml/Main.java
@@ -0,0 +1,48 @@
+/**
+ * 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 example.xml;
+
+import com.google.inject.Guice;
+import com.google.inject.AbstractModule;
+import com.google.inject.Injector;
+import java.net.URL;
+
+/**
+ *
+ *
+ */
+public class Main {
+
+  public static void main(String[] args) {
+    final URL xmlUrl = Main.class.getResource("phone.xml");
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Contacts.class).to(SimCard.class);
+        install(new XmlBeanModule(xmlUrl));
+      }
+    });
+
+    Phone phone = injector.getInstance(Phone.class);
+
+    if (phone.getContacts() == null) {
+      throw new AssertionError();
+    } else {
+      System.out.println("It worked!");
+    }
+  }
+}
diff --git a/examples/src/example/xml/Phone.java b/examples/src/example/xml/Phone.java
new file mode 100644
index 0000000..a48ddce
--- /dev/null
+++ b/examples/src/example/xml/Phone.java
@@ -0,0 +1,14 @@
+package example.xml;
+
+public class Phone {
+
+  Contacts contacts;
+
+  public void setContacts(Contacts contacts) {
+    this.contacts = contacts;
+  }
+
+  public Contacts getContacts() {
+    return contacts;
+  }
+}
diff --git a/examples/src/example/xml/SimCard.java b/examples/src/example/xml/SimCard.java
new file mode 100644
index 0000000..71cf39b
--- /dev/null
+++ b/examples/src/example/xml/SimCard.java
@@ -0,0 +1,10 @@
+package example.xml;
+
+import java.util.Collections;
+
+public class SimCard implements Contacts {
+
+  public Iterable<Contact> findByName(String name) {
+    return Collections.emptyList();
+  }
+}
\ No newline at end of file
diff --git a/examples/src/example/xml/XmlBeanModule.java b/examples/src/example/xml/XmlBeanModule.java
new file mode 100644
index 0000000..8701d68
--- /dev/null
+++ b/examples/src/example/xml/XmlBeanModule.java
@@ -0,0 +1,227 @@
+package example.xml;
+
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Binder;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import safesax.Element;
+import safesax.ElementListener;
+import safesax.Parsers;
+import safesax.RootElement;
+import safesax.StartElementListener;
+
+public class XmlBeanModule implements Module {
+
+  final URL xmlUrl;
+
+  Locator locator;
+  Binder originalBinder;
+  BeanBuilder beanBuilder;
+
+  public XmlBeanModule(URL xmlUrl) {
+    this.xmlUrl = xmlUrl;
+  }
+
+  public void configure(Binder binder) {
+    this.originalBinder = binder;
+
+    try {
+      RootElement beans = new RootElement("beans");
+      locator = beans.getLocator();
+
+      Element bean = beans.getChild("bean");
+      bean.setElementListener(new BeanListener());
+
+      Element property = bean.getChild("property");
+      property.setStartElementListener(new PropertyListener());
+
+      Reader in = new InputStreamReader(xmlUrl.openStream());
+      Parsers.parse(in, beans.getContentHandler());
+    }
+    catch (Exception e) {
+      originalBinder.addError(e);
+    }
+  }
+
+  /** Handles "binding" elements. */
+  class BeanListener implements ElementListener {
+
+    public void start(final Attributes attributes) {
+      Binder sourced = originalBinder.withSource(xmlSource());
+
+      String typeString = attributes.getValue("type");
+
+      // Make sure 'type' is present.
+      if (typeString == null) {
+        sourced.addError("Missing 'type' attribute.");
+        return;
+      }
+
+      // Resolve 'type'.
+      Class<?> type;
+      try {
+        type = Class.forName(typeString);
+      }
+      catch (ClassNotFoundException e) {
+        sourced.addError(e);
+        return;
+      }
+
+      // Look for a no-arg constructor.
+      try {
+        type.getConstructor();
+      }
+      catch (NoSuchMethodException e) {
+        sourced.addError("%s doesn't have a no-arg constructor.");
+        return;
+      }
+
+      // Create a bean builder for the given type.
+      beanBuilder = new BeanBuilder(type);
+    }
+
+    public void end() {
+      if (beanBuilder != null) {
+        beanBuilder.build();
+        beanBuilder = null;
+      }
+    }
+  }
+
+  /** Handles "property" elements. */
+  class PropertyListener implements StartElementListener {
+
+    public void start(final Attributes attributes) {
+      Binder sourced = originalBinder.withSource(xmlSource());
+
+      if (beanBuilder == null) {
+        // We must have already run into an error.
+        return;
+      }
+
+      // Check for 'name'.
+      String name = attributes.getValue("name");
+      if (name == null) {
+        sourced.addError("Missing attribute name.");
+        return;
+      }
+
+      Class<?> type = beanBuilder.type;
+
+      // Find setter method for the given property name.
+      String setterName = "set" + capitalize(name);
+      Method setter = null;
+      for (Method method : type.getMethods()) {
+        if (method.getName().equals(setterName)) {
+          setter = method;
+          break;
+        }
+      }
+      if (setter == null) {
+        sourced.addError("%s.%s() not found.", type.getName(), setterName);
+        return;
+      }
+
+      // Validate number of parameters.
+      Type[] parameterTypes = setter.getGenericParameterTypes();
+      if (parameterTypes.length != 1) {
+        sourced.addError("%s.%s() must take one argument.",
+            setterName, type.getName());
+        return;
+      }
+
+      // Add property descriptor to builder.
+      Provider<?> provider = sourced.getProvider(Key.get(parameterTypes[0]));
+      beanBuilder.properties.add(
+          new Property(setter, provider));
+    }
+  }
+
+  static String capitalize(String s) {
+    return Character.toUpperCase(s.charAt(0)) +
+        s.substring(1);
+  }
+
+  static class Property {
+
+    final Method setter;
+    final Provider<?> provider;
+
+    Property(Method setter, Provider<?> provider) {
+      this.setter = setter;
+      this.provider = provider;
+    }
+
+    void setOn(Object o) {
+      try {
+        setter.invoke(o, provider.get());
+      }
+      catch (IllegalAccessException e) {
+        throw new RuntimeException(e);
+      }
+      catch (InvocationTargetException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+
+  class BeanBuilder {
+    
+    final List<Property> properties = new ArrayList<Property>();
+    final Class<?> type;
+
+    BeanBuilder(Class<?> type) {
+      this.type = type;
+    }
+
+    void build() {
+      addBinding(type);
+    }
+
+    <T> void addBinding(Class<T> type) {
+      originalBinder.withSource(xmlSource())
+          .bind(type).toProvider(new BeanProvider<T>(type, properties));
+    }
+  }
+
+  static class BeanProvider<T> implements Provider<T> {
+
+    final Class<T> type;
+    final List<Property> properties;
+
+    BeanProvider(Class<T> type, List<Property> properties) {
+      this.type = type;
+      this.properties = properties;
+    }
+
+    public T get() {
+      try {
+        T t = type.newInstance();
+        for (Property property : properties) {
+          property.setOn(t);
+        }
+        return t;
+      }
+      catch (InstantiationException e) {
+        throw new RuntimeException(e);
+      }
+      catch (IllegalAccessException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+
+  Object xmlSource() {
+    return xmlUrl + ":" + locator.getLineNumber();
+  }
+}
diff --git a/examples/src/example/xml/phone.xml b/examples/src/example/xml/phone.xml
new file mode 100644
index 0000000..b14605e
--- /dev/null
+++ b/examples/src/example/xml/phone.xml
@@ -0,0 +1,5 @@
+<beans>
+  <bean type="example.xml.Phone">
+    <property name="contacts"/>
+  </bean>
+</beans>
\ No newline at end of file
diff --git a/extensions/assistedinject/.gitignore b/extensions/assistedinject/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/extensions/assistedinject/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/extensions/assistedinject/build.properties b/extensions/assistedinject/build.properties
new file mode 100644
index 0000000..9dce2f6
--- /dev/null
+++ b/extensions/assistedinject/build.properties
@@ -0,0 +1,7 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.assistedinject.FactoryProviderTest
+module=com.google.inject.assistedinject
+fragment=true
diff --git a/extensions/assistedinject/build.xml b/extensions/assistedinject/build.xml
new file mode 100644
index 0000000..c74a8f2
--- /dev/null
+++ b/extensions/assistedinject/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-assistedinject" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/assistedinject/pom.xml b/extensions/assistedinject/pom.xml
new file mode 100644
index 0000000..5fdb8b2
--- /dev/null
+++ b/extensions/assistedinject/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-assistedinject</artifactId>
+
+  <name>Google Guice - Extensions - AssistedInject</name>
+
+</project>
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/Assisted.java b/extensions/assistedinject/src/com/google/inject/assistedinject/Assisted.java
new file mode 100644
index 0000000..bdd633e
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/Assisted.java
@@ -0,0 +1,43 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates an injected parameter or field whose value comes from an argument to a factory method.
+ *
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
+public @interface Assisted {
+
+  /**
+   * The unique name for this parameter. This is matched to the {@literal @Assisted} constructor 
+   * parameter with the same value. Names are not necessary when the parameter types are distinct.
+   */
+  String value() default "";
+}
\ No newline at end of file
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedConstructor.java b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedConstructor.java
new file mode 100644
index 0000000..7ea0498
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedConstructor.java
@@ -0,0 +1,108 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Internal respresentation of a constructor annotated with
+ * {@link AssistedInject}
+ * 
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class AssistedConstructor<T> {
+
+  private final Constructor<T> constructor;
+  private final ParameterListKey assistedParameters;
+  private final List<Parameter> allParameters;
+  
+  public static <T> AssistedConstructor<T> create(
+      Constructor<T> constructor, List<TypeLiteral<?>> parameterTypes) {
+    return new AssistedConstructor<T>(constructor, parameterTypes);
+  }
+
+  private AssistedConstructor(Constructor<T> constructor, List<TypeLiteral<?>> parameterTypes) {
+    this.constructor = constructor;
+
+    Annotation[][] annotations = constructor.getParameterAnnotations();
+
+    List<Type> typeList = Lists.newArrayList();
+    allParameters = new ArrayList<Parameter>();
+
+    // categorize params as @Assisted or @Injected
+    for (int i = 0; i < parameterTypes.size(); i++) {
+      Parameter parameter = new Parameter(parameterTypes.get(i).getType(), annotations[i]);
+      allParameters.add(parameter);
+      if (parameter.isProvidedByFactory()) {
+        typeList.add(parameter.getType());
+      }
+    }
+    this.assistedParameters = new ParameterListKey(typeList);
+  }
+  
+  /**
+   * Returns the {@link ParameterListKey} for this constructor.  The
+   * {@link ParameterListKey} is created from the ordered list of {@link Assisted}
+   * constructor parameters.
+   */
+  public ParameterListKey getAssistedParameters() {
+    return assistedParameters;
+  }
+  
+  /**
+   * Returns an ordered list of all constructor parameters (both
+   * {@link Assisted} and {@link Inject}ed).
+   */
+  public List<Parameter> getAllParameters() {
+    return allParameters;
+  }
+
+  public Set<Class<?>> getDeclaredExceptions() {
+    return new HashSet<Class<?>>(Arrays.asList(constructor.getExceptionTypes()));
+  }
+  
+  /**
+   * Returns an instance of T, constructed using this constructor, with the
+   * supplied arguments.
+   */
+  public T newInstance(Object[] args) throws Throwable {
+    constructor.setAccessible(true);
+    try {
+      return constructor.newInstance(args);
+    } catch (InvocationTargetException e) {
+      throw e.getCause();
+    }
+  }
+  
+  @Override
+  public String toString() {
+    return constructor.toString();
+  }
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInject.java b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInject.java
new file mode 100644
index 0000000..b639229
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInject.java
@@ -0,0 +1,55 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.Inject;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * <p>
+ * When used in tandem with {@link FactoryModuleBuilder}, constructors annotated with 
+ * {@code @AssistedInject} indicate that multiple constructors can be injected, each with different
+ * parameters. AssistedInject annotations should not be mixed with {@literal @}{@link Inject}
+ * annotations. The assisted parameters must exactly match one corresponding factory method within
+ * the factory interface, but the parameters do not need to be in the same order. Constructors
+ * annotated with AssistedInject <b>are</b> created by Guice and receive all the benefits
+ * (such as AOP).
+ * 
+ * <p>
+ * <strong>Obsolete Usage:</strong> When used in tandem with {@link FactoryProvider}, constructors
+ * annotated with {@code @AssistedInject} trigger a "backwards compatibility mode". The assisted
+ * parameters must exactly match one corresponding factory method within the factory interface and
+ * all must be in the same order as listed in the factory. In this backwards compatable mode,
+ * constructors annotated with AssistedInject <b>are not</b> created by Guice and thus receive
+ * none of the benefits.
+ * 
+ * <p>
+ * Constructor parameters must be either supplied by the factory interface and marked with
+ * <code>@Assisted</code>, or they must be injectable.
+ * 
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+@Target( { CONSTRUCTOR })
+@Retention(RUNTIME)
+public @interface AssistedInject {
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectBinding.java b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectBinding.java
new file mode 100644
index 0000000..f598ba2
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectBinding.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2010 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.inject.assistedinject;
+
+import com.google.inject.Key;
+
+import java.util.Collection;
+
+/**
+ * A binding for a factory created by FactoryModuleBuilder.
+ * 
+ * @param <T> The fully qualified type of the factory.
+ *  
+ * @since 3.0
+ * @author ramakrishna@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedInjectBinding<T> {
+  
+  /** Returns the {@link Key} for the factory binding. */
+  Key<T> getKey();
+
+  /** Returns an {@link AssistedMethod} for each method in the factory. */
+  Collection<AssistedMethod> getAssistedMethods();
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor.java b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor.java
new file mode 100644
index 0000000..8e03a40
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2010 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.inject.assistedinject;
+
+import com.google.inject.spi.BindingTargetVisitor;
+
+/**
+ * A visitor for the AssistedInject extension.
+ * <p>
+ * If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ * {@link FactoryModuleBuilder} will be visited through this interface.
+ *
+ * @since 3.0
+ * @author ramakrishna@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedInjectTargetVisitor<T, V> extends BindingTargetVisitor<T, V> {
+  
+  /**
+   * Visits an {@link AssistedInjectBinding} created through {@link FactoryModuleBuilder}.
+   */
+  V visit(AssistedInjectBinding<? extends T> assistedInjectBinding);
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedMethod.java b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedMethod.java
new file mode 100644
index 0000000..08d7d6c
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedMethod.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2010 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.inject.assistedinject;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Dependency;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Details about how a method in an assisted inject factory will be assisted.
+ * 
+ * @since 3.0
+ * @author ramakrishna@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedMethod {
+  
+  /**
+   * Returns the factory method that is being assisted.
+   */
+  Method getFactoryMethod();
+  
+  /**
+   * Returns the implementation type that will be created when the method is
+   * used.
+   */
+  TypeLiteral<?> getImplementationType();
+
+  /**
+   * Returns the constructor that will be used to construct instances of the 
+   * implementation.
+   */
+  Constructor<?> getImplementationConstructor();
+  
+  /**
+   * Returns all non-assisted dependencies required to construct and inject
+   * the implementation.
+   */
+  Set<Dependency<?>> getDependencies();
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/BindingCollector.java b/extensions/assistedinject/src/com/google/inject/assistedinject/BindingCollector.java
new file mode 100644
index 0000000..a90494b
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/BindingCollector.java
@@ -0,0 +1,61 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Message;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Utility class for collecting factory bindings. Used for configuring {@link FactoryProvider2}.
+ *
+ * @author schmitt@google.com (Peter Schmitt)
+ */
+class BindingCollector {
+
+  private final Map<Key<?>, TypeLiteral<?>> bindings = Maps.newHashMap();
+
+  public BindingCollector addBinding(Key<?> key, TypeLiteral<?> target) {
+    if (bindings.containsKey(key)) {
+      throw new ConfigurationException(ImmutableSet.of(
+          new Message("Only one implementation can be specified for " + key)));
+    }
+
+    bindings.put(key, target);
+
+    return this;
+  }
+
+  public Map<Key<?>, TypeLiteral<?>> getBindings() {
+    return Collections.unmodifiableMap(bindings);
+  }
+
+  @Override
+  public int hashCode() {
+    return bindings.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    return (obj instanceof BindingCollector) && bindings.equals(((BindingCollector) obj).bindings);
+  }
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java
new file mode 100644
index 0000000..0ae096e
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java
@@ -0,0 +1,339 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Provides a factory that combines the caller's arguments with injector-supplied values to
+ * construct objects.
+ *
+ * <h3>Defining a factory</h3>
+ * Create an interface whose methods return the constructed type, or any of its supertypes. The
+ * method's parameters are the arguments required to build the constructed type.
+ *
+ * <pre>public interface PaymentFactory {
+ *   Payment create(Date startDate, Money amount);
+ * }</pre>
+ *
+ * You can name your factory methods whatever you like, such as <i>create</i>, <i>createPayment</i>
+ * or <i>newPayment</i>.
+ *
+ * <h3>Creating a type that accepts factory parameters</h3>
+ * {@code constructedType} is a concrete class with an {@literal @}{@link com.google.inject.Inject
+ * Inject}-annotated constructor. In addition to injector-supplied parameters, the constructor
+ * should have parameters that match each of the factory method's parameters. Each factory-supplied
+ * parameter requires an {@literal @}{@link Assisted} annotation. This serves to document that the
+ * parameter is not bound by your application's modules.
+ *
+ * <pre>public class RealPayment implements Payment {
+ *   {@literal @}Inject
+ *   public RealPayment(
+ *      CreditService creditService,
+ *      AuthService authService,
+ *      <strong>{@literal @}Assisted Date startDate</strong>,
+ *      <strong>{@literal @}Assisted Money amount</strong>) {
+ *     ...
+ *   }
+ * }</pre>
+ * 
+ * <h3>Multiple factory methods for the same type</h3>
+ * If the factory contains many methods that return the same type, you can create multiple
+ * constructors in your concrete class, each constructor marked with with
+ * {@literal @}{@link AssistedInject}, in order to match the different parameters types of the
+ * factory methods. 
+ * 
+ * <pre>public interface PaymentFactory {
+ *    Payment create(Date startDate, Money amount);
+ *    Payment createWithoutDate(Money amount);
+ * }
+ * 
+ * public class RealPayment implements Payment {
+ *  {@literal @}AssistedInject
+ *   public RealPayment(
+ *      CreditService creditService,
+ *      AuthService authService,
+ *     <strong>{@literal @}Assisted Date startDate</strong>,
+ *     <strong>{@literal @}Assisted Money amount</strong>) {
+ *     ...
+ *   }
+ *   
+ *  {@literal @}AssistedInject
+ *   public RealPayment(
+ *      CreditService creditService,
+ *      AuthService authService,
+ *     <strong>{@literal @}Assisted Money amount</strong>) {
+ *     ...
+ *   }   
+ * }</pre> 
+ *
+ * <h3>Configuring simple factories</h3>
+ * In your {@link Module module}, install a {@code FactoryModuleBuilder} that creates the
+ * factory:
+ *
+ * <pre>install(new FactoryModuleBuilder()
+ *     .implement(Payment.class, RealPayment.class)
+ *     .build(PaymentFactory.class));</pre>
+ *
+ * As a side-effect of this binding, Guice will inject the factory to initialize it for use. The
+ * factory cannot be used until the injector has been initialized.
+ * 
+ * <h3>Configuring complex factories</h3>
+ * Factories can create an arbitrary number of objects, one per each method.  Each factory
+ * method can be configured using <code>.implement</code>.
+ *
+ * <pre>public interface OrderFactory {
+ *    Payment create(Date startDate, Money amount);
+ *    Shipment create(Customer customer, Item item);
+ *    Receipt create(Payment payment, Shipment shipment);
+ * }
+ * 
+ * [...]
+ * 
+ * install(new FactoryModuleBuilder()
+ *     .implement(Payment.class, RealPayment.class)
+ *     // excluding .implement for Shipment means the implementation class
+ *     // will be 'Shipment' itself, which is legal if it's not an interface.
+ *     .implement(Receipt.class, RealReceipt.class)
+ *     .build(OrderFactory.class));</pre>
+ * </pre>
+ *
+ * <h3>Using the factory</h3>
+ * Inject your factory into your application classes. When you use the factory, your arguments
+ * will be combined with values from the injector to construct an instance.
+ *
+ * <pre>public class PaymentAction {
+ *   {@literal @}Inject private PaymentFactory paymentFactory;
+ *
+ *   public void doPayment(Money amount) {
+ *     Payment payment = paymentFactory.create(new Date(), amount);
+ *     payment.apply();
+ *   }
+ * }</pre>
+ *
+ * <h3>Making parameter types distinct</h3>
+ * The types of the factory method's parameters must be distinct. To use multiple parameters of
+ * the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the
+ * parameters. The names must be applied to the factory method's parameters:
+ *
+ * <pre>public interface PaymentFactory {
+ *   Payment create(
+ *       <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+ *       <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+ *       Money amount);
+ * } </pre>
+ *
+ * ...and to the concrete type's constructor parameters:
+ *
+ * <pre>public class RealPayment implements Payment {
+ *   {@literal @}Inject
+ *   public RealPayment(
+ *      CreditService creditService,
+ *      AuthService authService,
+ *      <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+ *      <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+ *      <strong>{@literal @}Assisted</strong> Money amount) {
+ *     ...
+ *   }
+ * }</pre>
+ *
+ * <h3>Values are created by Guice</h3>
+ * Returned factories use child injectors to create values. The values are eligible for method
+ * interception. In addition, {@literal @}{@literal Inject} members will be injected before they are
+ * returned.
+ *
+ * <h3>More configuration options</h3>
+ * In addition to simply specifying an implementation class for any returned type, factories' return
+ * values can be automatic or can be configured to use annotations:
+ * <p/>
+ * If you just want to return the types specified in the factory, do not configure any
+ * implementations:
+ *
+ * <pre>public interface FruitFactory {
+ *   Apple getApple(Color color);
+ * }
+ * ...
+ * protected void configure() {
+ *   install(new FactoryModuleBuilder().build(FruitFactory.class));
+ * }</pre>
+ *
+ * Note that any type returned by the factory in this manner needs to be an implementation class.
+ * <p/>
+ * To return two different implementations for the same interface from your factory, use binding
+ * annotations on your return types:
+ *
+ * <pre>interface CarFactory {
+ *   {@literal @}Named("fast") Car getFastCar(Color color);
+ *   {@literal @}Named("clean") Car getCleanCar(Color color);
+ * }
+ * ...
+ * protected void configure() {
+ *   install(new FactoryModuleBuilder()
+ *       .implement(Car.class, Names.named("fast"), Porsche.class)
+ *       .implement(Car.class, Names.named("clean"), Prius.class)
+ *       .build(CarFactory.class));
+ * }</pre>
+ * 
+ * <h3>Implementation limitations</h3>
+ * As a limitation of the implementation, it is prohibited to declare a factory method that
+ * accepts a {@code Provider} as one of its arguments.
+ *
+ * @since 3.0
+ * @author schmitt@google.com (Peter Schmitt)
+ */
+public final class FactoryModuleBuilder {
+
+  private final BindingCollector bindings = new BindingCollector();
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(Class<T> source, Class<? extends T> target) {
+    return implement(source, TypeLiteral.get(target));
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(Class<T> source, TypeLiteral<? extends T> target) {
+    return implement(TypeLiteral.get(source), target);
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, Class<? extends T> target) {
+    return implement(source, TypeLiteral.get(target));
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(TypeLiteral<T> source,
+      TypeLiteral<? extends T> target) {
+    return implement(Key.get(source), target);
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(Class<T> source, Annotation annotation,
+      Class<? extends T> target) {
+    return implement(source, annotation, TypeLiteral.get(target));
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(Class<T> source, Annotation annotation,
+      TypeLiteral<? extends T> target) {
+    return implement(TypeLiteral.get(source), annotation, target);
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, Annotation annotation,
+      Class<? extends T> target) {
+    return implement(source, annotation, TypeLiteral.get(target));
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, Annotation annotation,
+      TypeLiteral<? extends T> target) {
+    return implement(Key.get(source, annotation), target);
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(Class<T> source,
+      Class<? extends Annotation> annotationType, Class<? extends T> target) {
+    return implement(source, annotationType, TypeLiteral.get(target));
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(Class<T> source,
+      Class<? extends Annotation> annotationType, TypeLiteral<? extends T> target) {
+    return implement(TypeLiteral.get(source), annotationType, target);
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(TypeLiteral<T> source,
+      Class<? extends Annotation> annotationType, Class<? extends T> target) {
+    return implement(source, annotationType, TypeLiteral.get(target));
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(TypeLiteral<T> source,
+      Class<? extends Annotation> annotationType, TypeLiteral<? extends T> target) {
+    return implement(Key.get(source, annotationType), target);
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(Key<T> source, Class<? extends T> target) {
+    return implement(source, TypeLiteral.get(target));
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <T> FactoryModuleBuilder implement(Key<T> source, TypeLiteral<? extends T> target) {
+    bindings.addBinding(source, target);
+    return this;
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <F> Module build(Class<F> factoryInterface) {
+    return build(TypeLiteral.get(factoryInterface));
+  }
+
+  /**
+   * See the factory configuration examples at {@link FactoryModuleBuilder}.
+   */
+  public <F> Module build(TypeLiteral<F> factoryInterface) {
+    return build(Key.get(factoryInterface));
+  }
+
+
+  public <F> Module build(final Key<F> factoryInterface) {
+    return new AbstractModule() {
+      @Override protected void configure() {
+        Provider<F> provider = new FactoryProvider2<F>(factoryInterface, bindings);
+        bind(factoryInterface).toProvider(provider);
+      }
+    };
+  }
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java
new file mode 100644
index 0000000..b9619e3
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java
@@ -0,0 +1,400 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import static com.google.inject.internal.Annotations.getKey;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.BytecodeGen;
+import com.google.inject.internal.Errors;
+import com.google.inject.internal.ErrorsException;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.Message;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <strong>Obsolete.</strong> Prefer {@link FactoryModuleBuilder} for its more concise API and
+ * additional capability.
+ *
+ * <p>Provides a factory that combines the caller's arguments with injector-supplied values to
+ * construct objects.
+ *
+ * <h3>Defining a factory</h3>
+ * Create an interface whose methods return the constructed type, or any of its supertypes. The
+ * method's parameters are the arguments required to build the constructed type.
+ * <pre>public interface PaymentFactory {
+ *   Payment create(Date startDate, Money amount);
+ * }</pre>
+ * You can name your factory methods whatever you like, such as <i>create</i>, <i>createPayment</i>
+ * or <i>newPayment</i>.
+ *
+ * <h3>Creating a type that accepts factory parameters</h3>
+ * {@code constructedType} is a concrete class with an {@literal @}{@link Inject}-annotated
+ * constructor. In addition to injector-supplied parameters, the constructor should have
+ * parameters that match each of the factory method's parameters. Each factory-supplied parameter
+ * requires an {@literal @}{@link Assisted} annotation. This serves to document that the parameter
+ * is not bound by your application's modules.
+ * <pre>public class RealPayment implements Payment {
+ *   {@literal @}Inject
+ *   public RealPayment(
+ *      CreditService creditService,
+ *      AuthService authService,
+ *      <strong>{@literal @}Assisted Date startDate</strong>,
+ *      <strong>{@literal @}Assisted Money amount</strong>) {
+ *     ...
+ *   }
+ * }</pre>
+ * Any parameter that permits a null value should also be annotated {@code @Nullable}.
+ *
+ * <h3>Configuring factories</h3>
+ * In your {@link com.google.inject.Module module}, bind the factory interface to the returned
+ * factory:
+ * <pre>bind(PaymentFactory.class).toProvider(
+ *     FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));</pre>
+ * As a side-effect of this binding, Guice will inject the factory to initialize it for use. The
+ * factory cannot be used until the injector has been initialized.
+ *
+ * <h3>Using the factory</h3>
+ * Inject your factory into your application classes. When you use the factory, your arguments
+ * will be combined with values from the injector to construct an instance.
+ * <pre>public class PaymentAction {
+ *   {@literal @}Inject private PaymentFactory paymentFactory;
+ *
+ *   public void doPayment(Money amount) {
+ *     Payment payment = paymentFactory.create(new Date(), amount);
+ *     payment.apply();
+ *   }
+ * }</pre>
+ *
+ * <h3>Making parameter types distinct</h3>
+ * The types of the factory method's parameters must be distinct. To use multiple parameters of
+ * the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the
+ * parameters. The names must be applied to the factory method's parameters:
+ *
+ * <pre>public interface PaymentFactory {
+ *   Payment create(
+ *       <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+ *       <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+ *       Money amount);
+ * } </pre>
+ * ...and to the concrete type's constructor parameters:
+ * <pre>public class RealPayment implements Payment {
+ *   {@literal @}Inject
+ *   public RealPayment(
+ *      CreditService creditService,
+ *      AuthService authService,
+ *      <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+ *      <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+ *      <strong>{@literal @}Assisted</strong> Money amount) {
+ *     ...
+ *   }
+ * }</pre>
+ *
+ * <h3>Values are created by Guice</h3>
+ * Returned factories use child injectors to create values. The values are eligible for method
+ * interception. In addition, {@literal @}{@literal Inject} members will be injected before they are
+ * returned.
+ *
+ * <h3>Backwards compatibility using {@literal @}AssistedInject</h3>
+ * Instead of the {@literal @}Inject annotation, you may annotate the constructed classes with
+ * {@literal @}{@link AssistedInject}. This triggers a limited backwards-compatability mode.
+ *
+ * <p>Instead of matching factory method arguments to constructor parameters using their names, the
+ * <strong>parameters are matched by their order</strong>. The first factory method argument is
+ * used for the first {@literal @}Assisted constructor parameter, etc.. Annotation names have no
+ * effect.
+ *
+ * <p>Returned values are <strong>not created by Guice</strong>. These types are not eligible for
+ * method interception. They do receive post-construction member injection.
+ *
+ * @param <F> The factory interface
+ *
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @author dtm@google.com (Daniel Martin)
+ * 
+ * @deprecated use {@link FactoryModuleBuilder} instead.
+ */
+@Deprecated
+public class FactoryProvider<F> implements Provider<F>, HasDependencies {
+
+  /*
+   * This class implements the old @AssistedInject implementation that manually matches constructors
+   * to factory methods. The new child injector implementation lives in FactoryProvider2.
+   */
+
+  private Injector injector;
+
+  private final TypeLiteral<F> factoryType;
+  private final TypeLiteral<?> implementationType;
+  private final Map<Method, AssistedConstructor<?>> factoryMethodToConstructor;
+
+  public static <F> Provider<F> newFactory(Class<F> factoryType, Class<?> implementationType){
+    return newFactory(TypeLiteral.get(factoryType), TypeLiteral.get(implementationType));
+  }
+
+  public static <F> Provider<F> newFactory(
+      TypeLiteral<F> factoryType, TypeLiteral<?> implementationType) {
+    Map<Method, AssistedConstructor<?>> factoryMethodToConstructor
+        = createMethodMapping(factoryType, implementationType);
+
+    if (!factoryMethodToConstructor.isEmpty()) {
+      return new FactoryProvider<F>(factoryType, implementationType, factoryMethodToConstructor);
+    } else {
+      BindingCollector collector = new BindingCollector();
+
+      // Preserving backwards-compatibility:  Map all return types in a factory
+      // interface to the passed implementation type.
+      Errors errors = new Errors();
+      Key<?> implementationKey = Key.get(implementationType);
+
+      try {
+        for (Method method : factoryType.getRawType().getMethods()) {
+          Key<?> returnType = getKey(factoryType.getReturnType(method), method,
+              method.getAnnotations(), errors);
+          if (!implementationKey.equals(returnType)) {
+            collector.addBinding(returnType, implementationType);
+          }
+      }
+      } catch (ErrorsException e) {
+        throw new ConfigurationException(e.getErrors().getMessages());
+      }
+
+      return new FactoryProvider2<F>(Key.get(factoryType), collector);
+    }
+  }
+
+  private FactoryProvider(TypeLiteral<F> factoryType,
+      TypeLiteral<?> implementationType,
+      Map<Method, AssistedConstructor<?>> factoryMethodToConstructor) {
+    this.factoryType = factoryType;
+    this.implementationType = implementationType;
+    this.factoryMethodToConstructor = factoryMethodToConstructor;
+    checkDeclaredExceptionsMatch();
+  }
+
+  @Inject
+  void setInjectorAndCheckUnboundParametersAreInjectable(Injector injector) {
+    this.injector = injector;
+    for (AssistedConstructor<?> c : factoryMethodToConstructor.values()) {
+      for (Parameter p : c.getAllParameters()) {
+        if(!p.isProvidedByFactory() && !paramCanBeInjected(p, injector)) {
+          // this is lame - we're not using the proper mechanism to add an
+          // error to the injector. Throughout this class we throw exceptions
+          // to add errors, which isn't really the best way in Guice
+          throw newConfigurationException("Parameter of type '%s' is not injectable or annotated "
+                + "with @Assisted for Constructor '%s'", p, c);
+        }
+      }
+    }
+  }
+
+  private void checkDeclaredExceptionsMatch() {
+    for (Map.Entry<Method, AssistedConstructor<?>> entry : factoryMethodToConstructor.entrySet()) {
+      for (Class<?> constructorException : entry.getValue().getDeclaredExceptions()) {
+        if (!isConstructorExceptionCompatibleWithFactoryExeception(
+            constructorException, entry.getKey().getExceptionTypes())) {
+          throw newConfigurationException("Constructor %s declares an exception, but no compatible "
+              + "exception is thrown by the factory method %s", entry.getValue(), entry.getKey());
+        }
+      }
+    }
+  }
+
+  private boolean isConstructorExceptionCompatibleWithFactoryExeception(
+      Class<?> constructorException, Class<?>[] factoryExceptions) {
+    for (Class<?> factoryException : factoryExceptions) {
+      if (factoryException.isAssignableFrom(constructorException)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private boolean paramCanBeInjected(Parameter parameter, Injector injector) {
+    return parameter.isBound(injector);
+  }
+
+  private static Map<Method, AssistedConstructor<?>> createMethodMapping(
+      TypeLiteral<?> factoryType, TypeLiteral<?> implementationType) {
+    List<AssistedConstructor<?>> constructors = Lists.newArrayList();
+
+    for (Constructor<?> constructor : implementationType.getRawType().getDeclaredConstructors()) {
+      if (constructor.isAnnotationPresent(AssistedInject.class)) {
+        AssistedConstructor<?> assistedConstructor = AssistedConstructor.create(
+            constructor, implementationType.getParameterTypes(constructor));
+        constructors.add(assistedConstructor);
+      }
+    }
+
+    if (constructors.isEmpty()) {
+      return ImmutableMap.of();
+    }
+
+    Method[] factoryMethods = factoryType.getRawType().getMethods();
+
+    if (constructors.size() != factoryMethods.length) {
+      throw newConfigurationException("Constructor mismatch: %s has %s @AssistedInject "
+          + "constructors, factory %s has %s creation methods", implementationType,
+          constructors.size(), factoryType, factoryMethods.length);
+    }
+
+    Map<ParameterListKey, AssistedConstructor<?>> paramsToConstructor = Maps.newHashMap();
+
+    for (AssistedConstructor<?> c : constructors) {
+      if (paramsToConstructor.containsKey(c.getAssistedParameters())) {
+        throw new RuntimeException("Duplicate constructor, " + c);
+      }
+      paramsToConstructor.put(c.getAssistedParameters(), c);
+    }
+
+    Map<Method, AssistedConstructor<?>> result = Maps.newHashMap();
+    for (Method method : factoryMethods) {
+      if (!method.getReturnType().isAssignableFrom(implementationType.getRawType())) {
+        throw newConfigurationException("Return type of method %s is not assignable from %s",
+            method, implementationType);
+      }
+
+      List<Type> parameterTypes = Lists.newArrayList();
+      for (TypeLiteral<?> parameterType : factoryType.getParameterTypes(method)) {
+        parameterTypes.add(parameterType.getType());
+      }
+      ParameterListKey methodParams = new ParameterListKey(parameterTypes);
+
+      if (!paramsToConstructor.containsKey(methodParams)) {
+        throw newConfigurationException("%s has no @AssistInject constructor that takes the "
+            + "@Assisted parameters %s in that order. @AssistInject constructors are %s",
+            implementationType, methodParams, paramsToConstructor.values());
+      }
+
+      method.getParameterAnnotations();
+      for (Annotation[] parameterAnnotations : method.getParameterAnnotations()) {
+        for (Annotation parameterAnnotation : parameterAnnotations) {
+          if (parameterAnnotation.annotationType() == Assisted.class) {
+            throw newConfigurationException("Factory method %s has an @Assisted parameter, which "
+                + "is incompatible with the deprecated @AssistedInject annotation. Please replace "
+                + "@AssistedInject with @Inject on the %s constructor.",
+                method, implementationType);
+          }
+        }
+      }
+
+      AssistedConstructor<?> matchingConstructor = paramsToConstructor.remove(methodParams);
+
+      result.put(method, matchingConstructor);
+    }
+    return result;
+  }
+
+  public Set<Dependency<?>> getDependencies() {
+    List<Dependency<?>> dependencies = Lists.newArrayList();
+    for (AssistedConstructor<?> constructor : factoryMethodToConstructor.values()) {
+      for (Parameter parameter : constructor.getAllParameters()) {
+        if (!parameter.isProvidedByFactory()) {
+          dependencies.add(Dependency.get(parameter.getPrimaryBindingKey()));
+        }
+      }
+    }
+    return ImmutableSet.copyOf(dependencies);
+  }
+
+  public F get() {
+    InvocationHandler invocationHandler = new InvocationHandler() {
+      public Object invoke(Object proxy, Method method, Object[] creationArgs) throws Throwable {
+        // pass methods from Object.class to the proxy
+        if (method.getDeclaringClass().equals(Object.class)) {
+          if ("equals".equals(method.getName())) {
+            return proxy == creationArgs[0];
+          } else if ("hashCode".equals(method.getName())) {
+            return System.identityHashCode(proxy);
+          } else {
+            return method.invoke(this, creationArgs);
+          }
+        }
+
+        AssistedConstructor<?> constructor = factoryMethodToConstructor.get(method);
+        Object[] constructorArgs = gatherArgsForConstructor(constructor, creationArgs);
+        Object objectToReturn = constructor.newInstance(constructorArgs);
+        injector.injectMembers(objectToReturn);
+        return objectToReturn;
+      }
+
+      public Object[] gatherArgsForConstructor(
+          AssistedConstructor<?> constructor,
+          Object[] factoryArgs) {
+        int numParams = constructor.getAllParameters().size();
+        int argPosition = 0;
+        Object[] result = new Object[numParams];
+
+        for (int i = 0; i < numParams; i++) {
+          Parameter parameter = constructor.getAllParameters().get(i);
+          if (parameter.isProvidedByFactory()) {
+            result[i] = factoryArgs[argPosition];
+            argPosition++;
+          } else {
+            result[i] = parameter.getValue(injector);
+          }
+        }
+        return result;
+      }
+    };
+
+    @SuppressWarnings("unchecked") // we imprecisely treat the class literal of T as a Class<T>
+    Class<F> factoryRawType = (Class<F>) (Class<?>) factoryType.getRawType();
+    return factoryRawType.cast(Proxy.newProxyInstance(BytecodeGen.getClassLoader(factoryRawType),
+        new Class[] { factoryRawType }, invocationHandler));
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(factoryType, implementationType);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (!(obj instanceof FactoryProvider)) {
+      return false;
+    }
+    FactoryProvider<?> other = (FactoryProvider<?>) obj;
+    return factoryType.equals(other.factoryType)
+        && implementationType.equals(other.implementationType);
+  }
+
+  private static ConfigurationException newConfigurationException(String format, Object... args) {
+    return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args))));
+  }
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java
new file mode 100644
index 0000000..b40e19f
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java
@@ -0,0 +1,909 @@
+/**
+ * Copyright (C) 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.inject.assistedinject;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.Annotations;
+import com.google.inject.internal.BytecodeGen;
+import com.google.inject.internal.Errors;
+import com.google.inject.internal.ErrorsException;
+import com.google.inject.internal.UniqueAnnotations;
+import com.google.inject.internal.util.Classes;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+import com.google.inject.spi.Toolable;
+import com.google.inject.util.Providers;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * The newer implementation of factory provider. This implementation uses a child injector to
+ * create values.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @author dtm@google.com (Daniel Martin)
+ * @author schmitt@google.com (Peter Schmitt)
+ * @author sameb@google.com (Sam Berlin)
+ */
+final class FactoryProvider2 <F> implements InvocationHandler,
+    ProviderWithExtensionVisitor<F>, HasDependencies, AssistedInjectBinding<F> {
+
+  /** A constant annotation to denote the return value, instead of creating a new one each time. */
+  static final Annotation RETURN_ANNOTATION = UniqueAnnotations.create();
+
+  // use the logger under a well-known name, not FactoryProvider2
+  static final Logger logger = Logger.getLogger(AssistedInject.class.getName());
+
+  /** if a factory method parameter isn't annotated, it gets this annotation. */
+  static final Assisted DEFAULT_ANNOTATION = new Assisted() {
+    public String value() {
+      return "";
+    }
+
+    public Class<? extends Annotation> annotationType() {
+      return Assisted.class;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o instanceof Assisted && ((Assisted) o).value().isEmpty();
+    }
+
+    @Override public int hashCode() {
+      return 127 * "value".hashCode() ^ "".hashCode();
+    }
+
+    @Override public String toString() {
+      return "@" + Assisted.class.getName() + "(value=)";
+    }
+  };
+
+  /** All the data necessary to perform an assisted inject. */
+  private static class AssistData implements AssistedMethod {
+    /** the constructor the implementation is constructed with. */
+    final Constructor<?> constructor;
+    /** the return type in the factory method that the constructor is bound to. */
+    final Key<?> returnType;
+    /** the parameters in the factory method associated with this data. */
+    final ImmutableList<Key<?>> paramTypes;
+    /** the type of the implementation constructed */
+    final TypeLiteral<?> implementationType;
+
+    /** All non-assisted dependencies required by this method. */
+    final Set<Dependency<?>> dependencies;
+    /** The factory method associated with this data*/
+    final Method factoryMethod;
+
+    /** true if {@link #isValidForOptimizedAssistedInject} returned true. */
+    final boolean optimized;
+    /** the list of optimized providers, empty if not optimized. */
+    final List<ThreadLocalProvider> providers;
+    /** used to perform optimized factory creations. */
+    volatile Binding<?> cachedBinding; // TODO: volatile necessary?
+
+    AssistData(Constructor<?> constructor, Key<?> returnType, ImmutableList<Key<?>> paramTypes,
+        TypeLiteral<?> implementationType, Method factoryMethod,
+        Set<Dependency<?>> dependencies,
+        boolean optimized, List<ThreadLocalProvider> providers) {
+      this.constructor = constructor;
+      this.returnType = returnType;
+      this.paramTypes = paramTypes;
+      this.implementationType = implementationType;
+      this.factoryMethod = factoryMethod;
+      this.dependencies = dependencies;
+      this.optimized = optimized;
+      this.providers = providers;
+    }
+
+    @Override
+    public String toString() {
+      return Objects.toStringHelper(getClass())
+        .add("ctor", constructor)
+        .add("return type", returnType)
+        .add("param type", paramTypes)
+        .add("implementation type", implementationType)
+        .add("dependencies", dependencies)
+        .add("factory method", factoryMethod)
+        .add("optimized", optimized)
+        .add("providers", providers)
+        .add("cached binding", cachedBinding)
+        .toString();
+    }
+
+    public Set<Dependency<?>> getDependencies() {
+      return dependencies;
+    }
+
+    public Method getFactoryMethod() {
+      return factoryMethod;
+    }
+
+    public Constructor<?> getImplementationConstructor() {
+      return constructor;
+    }
+
+    public TypeLiteral<?> getImplementationType() {
+      return implementationType;
+    }
+  }
+
+  /** Mapping from method to the data about how the method will be assisted. */
+  private final ImmutableMap<Method, AssistData> assistDataByMethod;
+
+  /** Mapping from method to method handle, for generated default methods. */
+  private final ImmutableMap<Method, MethodHandleWrapper> methodHandleByMethod;
+
+  /** the hosting injector, or null if we haven't been initialized yet */
+  private Injector injector;
+
+  /** the factory interface, implemented and provided */
+  private final F factory;
+  
+  /** The key that this is bound to. */
+  private final Key<F> factoryKey;
+  
+  /** The binding collector, for equality/hashing purposes. */
+  private final BindingCollector collector;
+
+  /**
+   * @param factoryKey a key for a Java interface that defines one or more create methods.
+   * @param collector binding configuration that maps method return types to
+   *    implementation types.
+   */
+  FactoryProvider2(Key<F> factoryKey, BindingCollector collector) {
+    this.factoryKey = factoryKey;
+    this.collector = collector;
+
+    TypeLiteral<F> factoryType = factoryKey.getTypeLiteral();
+    Errors errors = new Errors();
+
+    @SuppressWarnings("unchecked") // we imprecisely treat the class literal of T as a Class<T>
+    Class<F> factoryRawType = (Class<F>) (Class<?>) factoryType.getRawType();
+
+    try {
+      if(!factoryRawType.isInterface()) {
+        throw errors.addMessage("%s must be an interface.", factoryRawType).toException();
+      }
+
+      Multimap<String, Method> defaultMethods = HashMultimap.create();
+      Multimap<String, Method> otherMethods = HashMultimap.create();
+      ImmutableMap.Builder<Method, AssistData> assistDataBuilder = ImmutableMap.builder();
+      // TODO: also grab methods from superinterfaces
+      for (Method method : factoryRawType.getMethods()) {
+        // Skip default methods that java8 may have created.
+        if (isDefault(method) && (method.isBridge() || method.isSynthetic())) {
+          // Even synthetic default methods need the return type validation...
+          // unavoidable consequence of javac8. :-(
+          validateFactoryReturnType(errors, method.getReturnType(), factoryRawType);
+          defaultMethods.put(method.getName(), method);
+          continue;
+        }
+        otherMethods.put(method.getName(), method);
+
+        TypeLiteral<?> returnTypeLiteral = factoryType.getReturnType(method);
+        Key<?> returnType;
+        try {
+          returnType = Annotations.getKey(returnTypeLiteral, method, method.getAnnotations(), errors);
+        } catch(ConfigurationException ce) {
+          // If this was an error due to returnTypeLiteral not being specified, rephrase
+          // it as our factory not being specified, so it makes more sense to users.
+          if(isTypeNotSpecified(returnTypeLiteral, ce)) {
+            throw errors.keyNotFullySpecified(TypeLiteral.get(factoryRawType)).toException();
+          } else {
+            throw ce;
+          }
+        }
+        validateFactoryReturnType(errors, returnType.getTypeLiteral().getRawType(), factoryRawType);
+        List<TypeLiteral<?>> params = factoryType.getParameterTypes(method);
+        Annotation[][] paramAnnotations = method.getParameterAnnotations();
+        int p = 0;
+        List<Key<?>> keys = Lists.newArrayList();
+        for (TypeLiteral<?> param : params) {
+          Key<?> paramKey = Annotations.getKey(param, method, paramAnnotations[p++], errors);
+          Class<?> underlylingType = paramKey.getTypeLiteral().getRawType();
+          if (underlylingType.equals(Provider.class)
+              || underlylingType.equals(javax.inject.Provider.class)) {
+            errors.addMessage("A Provider may not be a type in a factory method of an AssistedInject."
+                    + "\n  Offending instance is parameter [%s] with key [%s] on method [%s]",
+                    p, paramKey, method);
+          }
+          keys.add(assistKey(method, paramKey, errors));
+        }
+        ImmutableList<Key<?>> immutableParamList = ImmutableList.copyOf(keys);
+
+        // try to match up the method to the constructor
+        TypeLiteral<?> implementation = collector.getBindings().get(returnType);
+        if(implementation == null) {
+          implementation = returnType.getTypeLiteral();
+        }
+        Class<? extends Annotation> scope =
+            Annotations.findScopeAnnotation(errors, implementation.getRawType());
+        if (scope != null) {
+          errors.addMessage("Found scope annotation [%s] on implementation class "
+              + "[%s] of AssistedInject factory [%s].\nThis is not allowed, please"
+              + " remove the scope annotation.",
+              scope, implementation.getRawType(), factoryType);
+        }
+        
+        InjectionPoint ctorInjectionPoint;
+        try {
+          ctorInjectionPoint =
+            findMatchingConstructorInjectionPoint(method, returnType, implementation, immutableParamList);
+        } catch(ErrorsException ee) {
+          errors.merge(ee.getErrors());
+          continue;
+        }
+
+        Constructor<?> constructor = (Constructor<?>) ctorInjectionPoint.getMember();
+        List<ThreadLocalProvider> providers = Collections.emptyList();
+        Set<Dependency<?>> deps = getDependencies(ctorInjectionPoint, implementation);
+        boolean optimized = false;
+        // Now go through all dependencies of the implementation and see if it is OK to
+        // use an optimized form of assistedinject2.  The optimized form requires that
+        // all injections directly inject the object itself (and not a Provider of the object,
+        // or an Injector), because it caches a single child injector and mutates the Provider
+        // of the arguments in a ThreadLocal.
+        if(isValidForOptimizedAssistedInject(deps, implementation.getRawType(), factoryType)) {
+          ImmutableList.Builder<ThreadLocalProvider> providerListBuilder = ImmutableList.builder();
+          for(int i = 0; i < params.size(); i++) {
+            providerListBuilder.add(new ThreadLocalProvider());
+          }
+          providers = providerListBuilder.build();
+          optimized = true;
+        }
+
+        AssistData data = new AssistData(constructor,
+            returnType,
+            immutableParamList,
+            implementation,
+            method,
+            removeAssistedDeps(deps),
+            optimized,
+            providers);
+        assistDataBuilder.put(method, data);
+      }
+
+      factory = factoryRawType.cast(Proxy.newProxyInstance(
+          BytecodeGen.getClassLoader(factoryRawType), new Class<?>[] {factoryRawType}, this));
+
+      // Now go back through default methods. Try to use MethodHandles to make things
+      // work.  If that doesn't work, fallback to trying to find compatible method
+      // signatures.
+      Map<Method, AssistData> dataSoFar = assistDataBuilder.build();
+      ImmutableMap.Builder<Method, MethodHandleWrapper> methodHandleBuilder = ImmutableMap.builder();
+      for (Map.Entry<String, Method> entry : defaultMethods.entries()) {
+        Method defaultMethod = entry.getValue();
+        MethodHandleWrapper handle = MethodHandleWrapper.create(defaultMethod, factory);
+        if (handle != null) {
+          methodHandleBuilder.put(defaultMethod, handle);
+        } else {
+          boolean foundMatch = false;
+          for (Method otherMethod : otherMethods.get(defaultMethod.getName())) {
+            if (dataSoFar.containsKey(otherMethod) && isCompatible(defaultMethod, otherMethod)) {
+              if (foundMatch) {
+                errors.addMessage("Generated default method %s with parameters %s is"
+                    + " signature-compatible with more than one non-default method."
+                    + " Unable to create factory. As a workaround, remove the override"
+                    + " so javac stops generating a default method.",
+                    defaultMethod, Arrays.asList(defaultMethod.getParameterTypes()));
+              } else {
+                assistDataBuilder.put(defaultMethod, dataSoFar.get(otherMethod));
+                foundMatch = true;
+              }
+            }
+          }
+          if (!foundMatch) {
+            throw new IllegalStateException("Can't find method compatible with: " + defaultMethod);
+          }
+        }
+      }
+
+      // If we generated any errors (from finding matching constructors, for instance), throw an exception.
+      if(errors.hasErrors()) {
+        throw errors.toException();
+      }
+
+      assistDataByMethod = assistDataBuilder.build();
+      methodHandleByMethod = methodHandleBuilder.build();
+    } catch (ErrorsException e) {
+      throw new ConfigurationException(e.getErrors().getMessages());
+    }
+  }
+
+  static boolean isDefault(Method method) {
+    // Per the javadoc, default methods are non-abstract, public, non-static.
+    // They're also in interfaces, but we can guarantee that already since we only act
+    // on interfaces.
+    return (method.getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC))
+        == Modifier.PUBLIC;
+  }
+
+  private boolean isCompatible(Method src, Method dst) {
+    if (!src.getReturnType().isAssignableFrom(dst.getReturnType())) {
+      return false;
+    }
+    Class<?>[] srcParams = src.getParameterTypes();
+    Class<?>[] dstParams = dst.getParameterTypes();
+    if (srcParams.length != dstParams.length) {
+      return false;
+    }
+    for (int i = 0; i < srcParams.length; i++) {
+      if (!srcParams[i].isAssignableFrom(dstParams[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public F get() {
+    return factory;
+  }
+
+  public Set<Dependency<?>> getDependencies() {
+    Set<Dependency<?>> combinedDeps = new HashSet<Dependency<?>>();
+    for(AssistData data : assistDataByMethod.values()) {
+      combinedDeps.addAll(data.dependencies);
+    }
+    return ImmutableSet.copyOf(combinedDeps);
+  }
+  
+  public Key<F> getKey() {
+    return factoryKey;
+  }
+
+  // Safe cast because values are typed to AssistedData, which is an AssistedMethod, and
+  // the collection is immutable.
+  @SuppressWarnings("unchecked")
+  public Collection<AssistedMethod> getAssistedMethods() {
+    return (Collection<AssistedMethod>) (Collection<?>) assistDataByMethod.values();
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T, V> V acceptExtensionVisitor(BindingTargetVisitor<T, V> visitor,
+      ProviderInstanceBinding<? extends T> binding) {
+    if (visitor instanceof AssistedInjectTargetVisitor) {
+      return ((AssistedInjectTargetVisitor<T, V>)visitor).visit((AssistedInjectBinding<T>)this);
+    }
+    return visitor.visit(binding);
+  }
+
+  private void validateFactoryReturnType(Errors errors, Class<?> returnType, Class<?> factoryType) {
+    if (Modifier.isPublic(factoryType.getModifiers())
+        && !Modifier.isPublic(returnType.getModifiers())) {
+      errors.addMessage("%s is public, but has a method that returns a non-public type: %s. "
+          + "Due to limitations with java.lang.reflect.Proxy, this is not allowed. "
+          + "Please either make the factory non-public or the return type public.",
+          factoryType, returnType);
+    }
+  }
+
+  /**
+   * Returns true if the ConfigurationException is due to an error of TypeLiteral not being fully
+   * specified.
+   */
+  private boolean isTypeNotSpecified(TypeLiteral<?> typeLiteral, ConfigurationException ce) {
+    Collection<Message> messages = ce.getErrorMessages();
+    if (messages.size() == 1) {
+      Message msg = Iterables.getOnlyElement(
+          new Errors().keyNotFullySpecified(typeLiteral).getMessages());
+      return msg.getMessage().equals(Iterables.getOnlyElement(messages).getMessage());
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Finds a constructor suitable for the method.  If the implementation contained any constructors
+   * marked with {@link AssistedInject}, this requires all {@link Assisted} parameters to exactly
+   * match the parameters (in any order) listed in the method.  Otherwise, if no
+   * {@link AssistedInject} constructors exist, this will default to looking for an
+   * {@literal @}{@link Inject} constructor.
+   */
+  private <T> InjectionPoint findMatchingConstructorInjectionPoint(
+      Method method, Key<?> returnType, TypeLiteral<T> implementation, List<Key<?>> paramList)
+      throws ErrorsException {
+    Errors errors = new Errors(method);
+    if(returnType.getTypeLiteral().equals(implementation)) {
+      errors = errors.withSource(implementation);
+    } else {
+      errors = errors.withSource(returnType).withSource(implementation);
+    }
+
+    Class<?> rawType = implementation.getRawType();
+    if (Modifier.isInterface(rawType.getModifiers())) {
+      errors.addMessage(
+          "%s is an interface, not a concrete class.  Unable to create AssistedInject factory.",
+          implementation);
+      throw errors.toException();
+    } else if (Modifier.isAbstract(rawType.getModifiers())) {
+      errors.addMessage(
+          "%s is abstract, not a concrete class.  Unable to create AssistedInject factory.",
+          implementation);
+      throw errors.toException();
+    } else if (Classes.isInnerClass(rawType)) {
+      errors.cannotInjectInnerClass(rawType);
+      throw errors.toException();
+    }
+
+    Constructor<?> matchingConstructor = null;
+    boolean anyAssistedInjectConstructors = false;
+    // Look for AssistedInject constructors...
+    for (Constructor<?> constructor : rawType.getDeclaredConstructors()) {
+      if (constructor.isAnnotationPresent(AssistedInject.class)) {
+        anyAssistedInjectConstructors = true;
+        if (constructorHasMatchingParams(implementation, constructor, paramList, errors)) {
+          if (matchingConstructor != null) {
+            errors
+                .addMessage(
+                    "%s has more than one constructor annotated with @AssistedInject"
+                        + " that matches the parameters in method %s.  Unable to create "
+                        + "AssistedInject factory.",
+                    implementation, method);
+            throw errors.toException();
+          } else {
+            matchingConstructor = constructor;
+          }
+        }
+      }
+    }
+
+    if(!anyAssistedInjectConstructors) {
+      // If none existed, use @Inject.
+      try {
+        return InjectionPoint.forConstructorOf(implementation);
+      } catch(ConfigurationException e) {
+        errors.merge(e.getErrorMessages());
+        throw errors.toException();
+      }
+    } else {
+      // Otherwise, use it or fail with a good error message.
+      if(matchingConstructor != null) {
+          // safe because we got the constructor from this implementation.
+          @SuppressWarnings("unchecked")
+          InjectionPoint ip = InjectionPoint.forConstructor(
+              (Constructor<? super T>) matchingConstructor, implementation);
+          return ip;
+      } else {
+        errors.addMessage(
+            "%s has @AssistedInject constructors, but none of them match the"
+            + " parameters in method %s.  Unable to create AssistedInject factory.",
+            implementation, method);
+        throw errors.toException();
+      }
+    }
+  }
+
+  /**
+   * Matching logic for constructors annotated with AssistedInject.
+   * This returns true if and only if all @Assisted parameters in the
+   * constructor exactly match (in any order) all @Assisted parameters
+   * the method's parameter.
+   */
+  private boolean constructorHasMatchingParams(TypeLiteral<?> type,
+      Constructor<?> constructor, List<Key<?>> paramList, Errors errors)
+      throws ErrorsException {
+    List<TypeLiteral<?>> params = type.getParameterTypes(constructor);
+    Annotation[][] paramAnnotations = constructor.getParameterAnnotations();
+    int p = 0;
+    List<Key<?>> constructorKeys = Lists.newArrayList();
+    for (TypeLiteral<?> param : params) {
+      Key<?> paramKey = Annotations.getKey(param, constructor, paramAnnotations[p++],
+          errors);
+      constructorKeys.add(paramKey);
+    }
+    // Require that every key exist in the constructor to match up exactly.
+    for (Key<?> key : paramList) {
+      // If it didn't exist in the constructor set, we can't use it.
+      if (!constructorKeys.remove(key)) {
+        return false;
+      }
+    }
+    // If any keys remain and their annotation is Assisted, we can't use it.
+    for (Key<?> key : constructorKeys) {
+      if (key.getAnnotationType() == Assisted.class) {
+        return false;
+      }
+    }
+    // All @Assisted params match up to the method's parameters.
+    return true;
+  }
+
+  /** Calculates all dependencies required by the implementation and constructor. */
+  private Set<Dependency<?>> getDependencies(InjectionPoint ctorPoint, TypeLiteral<?> implementation) {
+    ImmutableSet.Builder<Dependency<?>> builder = ImmutableSet.builder();
+    builder.addAll(ctorPoint.getDependencies());
+    if (!implementation.getRawType().isInterface()) {
+      for (InjectionPoint ip : InjectionPoint.forInstanceMethodsAndFields(implementation)) {
+        builder.addAll(ip.getDependencies());
+      }
+    }
+    return builder.build();
+  }
+
+  /** Return all non-assisted dependencies. */
+  private Set<Dependency<?>> removeAssistedDeps(Set<Dependency<?>> deps) {
+    ImmutableSet.Builder<Dependency<?>> builder = ImmutableSet.builder();
+    for(Dependency<?> dep : deps) {
+      Class<?> annotationType = dep.getKey().getAnnotationType();
+      if (annotationType == null || !annotationType.equals(Assisted.class)) {
+        builder.add(dep);
+      }
+    }
+    return builder.build();
+  }
+
+  /**
+   * Returns true if all dependencies are suitable for the optimized version of AssistedInject. The
+   * optimized version caches the binding & uses a ThreadLocal Provider, so can only be applied if
+   * the assisted bindings are immediately provided. This looks for hints that the values may be
+   * lazily retrieved, by looking for injections of Injector or a Provider for the assisted values.
+   */
+  private boolean isValidForOptimizedAssistedInject(Set<Dependency<?>> dependencies,
+      Class<?> implementation, TypeLiteral<?> factoryType) {
+    Set<Dependency<?>> badDeps = null; // optimization: create lazily
+    for (Dependency<?> dep : dependencies) {
+      if (isInjectorOrAssistedProvider(dep)) {
+        if (badDeps == null) {
+          badDeps = Sets.newHashSet();
+        }
+        badDeps.add(dep);
+      }
+    }
+    if (badDeps != null && !badDeps.isEmpty()) {
+      logger.log(Level.WARNING, "AssistedInject factory {0} will be slow "
+          + "because {1} has assisted Provider dependencies or injects the Injector. "
+          + "Stop injecting @Assisted Provider<T> (instead use @Assisted T) "
+          + "or Injector to speed things up. (It will be a ~6500% speed bump!)  "
+          + "The exact offending deps are: {2}",
+          new Object[] {factoryType, implementation, badDeps} );
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Returns true if the dependency is for {@link Injector} or if the dependency
+   * is a {@link Provider} for a parameter that is {@literal @}{@link Assisted}.
+   */
+  private boolean isInjectorOrAssistedProvider(Dependency<?> dependency) {
+    Class<?> annotationType = dependency.getKey().getAnnotationType();
+    if (annotationType != null && annotationType.equals(Assisted.class)) { // If it's assisted..
+      if (dependency.getKey().getTypeLiteral().getRawType().equals(Provider.class)) { // And a Provider...
+        return true;
+      }
+    } else if (dependency.getKey().getTypeLiteral().getRawType().equals(Injector.class)) { // If it's the Injector...
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Returns a key similar to {@code key}, but with an {@literal @}Assisted binding annotation.
+   * This fails if another binding annotation is clobbered in the process. If the key already has
+   * the {@literal @}Assisted annotation, it is returned as-is to preserve any String value.
+   */
+  private <T> Key<T> assistKey(Method method, Key<T> key, Errors errors) throws ErrorsException {
+    if (key.getAnnotationType() == null) {
+      return Key.get(key.getTypeLiteral(), DEFAULT_ANNOTATION);
+    } else if (key.getAnnotationType() == Assisted.class) {
+      return key;
+    } else {
+      errors.withSource(method).addMessage(
+          "Only @Assisted is allowed for factory parameters, but found @%s",
+          key.getAnnotationType());
+      throw errors.toException();
+    }
+  }
+
+  /**
+   * At injector-creation time, we initialize the invocation handler. At this time we make sure
+   * all factory methods will be able to build the target types.
+   */
+  @Inject @Toolable
+  void initialize(Injector injector) {
+    if (this.injector != null) {
+      throw new ConfigurationException(ImmutableList.of(new Message(FactoryProvider2.class,
+          "Factories.create() factories may only be used in one Injector!")));
+    }
+
+    this.injector = injector;
+
+    for (Map.Entry<Method, AssistData> entry : assistDataByMethod.entrySet()) {
+      Method method = entry.getKey();
+      AssistData data = entry.getValue();
+      Object[] args;
+      if(!data.optimized) {
+        args = new Object[method.getParameterTypes().length];
+        Arrays.fill(args, "dummy object for validating Factories");
+      } else {
+        args = null; // won't be used -- instead will bind to data.providers.
+      }
+      getBindingFromNewInjector(method, args, data); // throws if the binding isn't properly configured
+    }
+  }
+
+  /**
+   * Creates a child injector that binds the args, and returns the binding for the method's result.
+   */
+  public Binding<?> getBindingFromNewInjector(
+      final Method method, final Object[] args, final AssistData data) {
+    checkState(injector != null,
+        "Factories.create() factories cannot be used until they're initialized by Guice.");
+
+    final Key<?> returnType = data.returnType;
+
+    // We ignore any pre-existing binding annotation.
+    final Key<?> returnKey = Key.get(returnType.getTypeLiteral(), RETURN_ANNOTATION);
+
+    Module assistedModule = new AbstractModule() {
+      @Override
+      @SuppressWarnings({
+        "unchecked", "rawtypes"}) // raw keys are necessary for the args array and return value
+      protected void configure() {
+        Binder binder = binder().withSource(method);
+
+        int p = 0;
+        if(!data.optimized) {
+          for (Key<?> paramKey : data.paramTypes) {
+            // Wrap in a Provider to cover null, and to prevent Guice from injecting the parameter
+            binder.bind((Key) paramKey).toProvider(Providers.of(args[p++]));
+          }
+        } else {
+          for (Key<?> paramKey : data.paramTypes) {
+            // Bind to our ThreadLocalProviders.
+            binder.bind((Key) paramKey).toProvider(data.providers.get(p++));
+          }
+        }
+
+        Constructor constructor = data.constructor;
+        // Constructor *should* always be non-null here,
+        // but if it isn't, we'll end up throwing a fairly good error
+        // message for the user.
+        if(constructor != null) {
+          binder.bind(returnKey)
+              .toConstructor(constructor, (TypeLiteral)data.implementationType)
+              .in(Scopes.NO_SCOPE); // make sure we erase any scope on the implementation type
+        }
+      }
+    };
+
+    Injector forCreate = injector.createChildInjector(assistedModule);
+    Binding<?> binding = forCreate.getBinding(returnKey);
+    // If we have providers cached in data, cache the binding for future optimizations.
+    if(data.optimized) {
+      data.cachedBinding = binding;
+    }
+    return binding;
+  }
+
+  /**
+   * When a factory method is invoked, we create a child injector that binds all parameters, then
+   * use that to get an instance of the return type.
+   */
+  public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
+    // If we setup a method handle earlier for this method, call it.
+    // This is necessary for default methods that java8 creates, so we
+    // can call the default method implementation (and not our proxied version of it).
+    if (methodHandleByMethod.containsKey(method)) {
+      return methodHandleByMethod.get(method).invokeWithArguments(args);
+    }
+
+    if (method.getDeclaringClass().equals(Object.class)) {
+      if ("equals".equals(method.getName())) {
+        return proxy == args[0];
+      } else if ("hashCode".equals(method.getName())) {
+        return System.identityHashCode(proxy);
+      } else {
+        return method.invoke(this, args);
+      }
+    }
+
+    AssistData data = assistDataByMethod.get(method);
+    checkState(data != null, "No data for method: %s", method);
+    Provider<?> provider;
+    if(data.cachedBinding != null) { // Try to get optimized form...
+      provider = data.cachedBinding.getProvider();
+    } else {
+      provider = getBindingFromNewInjector(method, args, data).getProvider();
+    }
+    try {
+      int p = 0;
+      for(ThreadLocalProvider tlp : data.providers) {
+        tlp.set(args[p++]);
+      }
+      return provider.get();
+    } catch (ProvisionException e) {
+      // if this is an exception declared by the factory method, throw it as-is
+      if (e.getErrorMessages().size() == 1) {
+        Message onlyError = getOnlyElement(e.getErrorMessages());
+        Throwable cause = onlyError.getCause();
+        if (cause != null && canRethrow(method, cause)) {
+          throw cause;
+        }
+      }
+      throw e;
+    } finally {
+      for(ThreadLocalProvider tlp : data.providers) {
+        tlp.remove();
+      }
+    }
+  }
+
+  @Override public String toString() {
+    return factory.getClass().getInterfaces()[0].getName();
+  }
+  
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(factoryKey, collector);
+  }
+
+  @Override public boolean equals(Object obj) {
+    if (!(obj instanceof FactoryProvider2)) {
+      return false;
+    }
+    FactoryProvider2<?> other = (FactoryProvider2<?>) obj;
+    return factoryKey.equals(other.factoryKey) && Objects.equal(collector, other.collector);
+  }
+
+  /** Returns true if {@code thrown} can be thrown by {@code invoked} without wrapping. */
+  static boolean canRethrow(Method invoked, Throwable thrown) {
+    if (thrown instanceof Error || thrown instanceof RuntimeException) {
+      return true;
+    }
+
+    for (Class<?> declared : invoked.getExceptionTypes()) {
+      if (declared.isInstance(thrown)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  // not <T> because we'll never know and this is easier than suppressing warnings.
+  private static class ThreadLocalProvider extends ThreadLocal<Object> implements Provider<Object> {
+    @Override
+    protected Object initialValue() {
+      throw new IllegalStateException(
+          "Cannot use optimized @Assisted provider outside the scope of the constructor."
+              + " (This should never happen.  If it does, please report it.)");
+    }
+  }
+
+  /** Wrapper around MethodHandles/MethodHandle, so we can compile+run on java6. */
+  private static class MethodHandleWrapper {
+    static final int ALL_MODES = Modifier.PRIVATE
+        | Modifier.STATIC /* package */
+        | Modifier.PUBLIC
+        | Modifier.PROTECTED;
+    
+    static final Method unreflectSpecial;
+    static final Method bindTo;
+    static final Method invokeWithArguments;
+    static final Constructor<?> lookupCxtor;
+    static final boolean valid;
+
+    static {
+      Method unreflectSpecialTmp = null;
+      Method bindToTmp = null;
+      Method invokeWithArgumentsTmp = null;
+      boolean validTmp = false;
+      Constructor<?> lookupCxtorTmp = null;
+      try {
+        Class<?> lookupClass = Class.forName("java.lang.invoke.MethodHandles$Lookup");
+        unreflectSpecialTmp = lookupClass.getMethod("unreflectSpecial", Method.class, Class.class);
+        Class<?> methodHandleClass = Class.forName("java.lang.invoke.MethodHandle");
+        bindToTmp = methodHandleClass.getMethod("bindTo", Object.class);
+        invokeWithArgumentsTmp = methodHandleClass.getMethod("invokeWithArguments", Object[].class);
+        lookupCxtorTmp = lookupClass.getDeclaredConstructor(Class.class, int.class);
+        lookupCxtorTmp.setAccessible(true);
+        validTmp = true;
+      } catch (Exception invalid) {
+        // Ignore the exception, store the values & exit early in create(..) if invalid.
+      }
+
+      // Store refs to later.
+      valid = validTmp;
+      unreflectSpecial = unreflectSpecialTmp;
+      bindTo = bindToTmp;
+      invokeWithArguments = invokeWithArgumentsTmp;
+      lookupCxtor = lookupCxtorTmp;
+    }
+
+    static MethodHandleWrapper create(Method method, Object proxy) {
+      if (!valid) {
+        return null;
+      }
+      try {
+        Class<?> declaringClass = method.getDeclaringClass();
+        // Note: this isn't a public API, but we need to use it in order to call default methods.
+        Object lookup = lookupCxtor.newInstance(declaringClass, ALL_MODES);
+        method.setAccessible(true);
+        // These are part of the public API, but we use reflection since we run on java6
+        // and they were introduced in java7.
+        lookup = unreflectSpecial.invoke(lookup, method, declaringClass);
+        Object handle = bindTo.invoke(lookup, proxy);
+        return new MethodHandleWrapper(handle);
+      } catch (InvocationTargetException ite) {
+        return null;
+      } catch (IllegalAccessException iae) {
+        return null;
+      } catch (InstantiationException ie) {
+        return null;
+      }
+    }
+
+    final Object handle;
+
+    MethodHandleWrapper(Object handle) {
+      this.handle = handle;
+    }
+
+    Object invokeWithArguments(Object[] args) throws Exception {
+      // We must cast the args to an object so the Object[] is the first param,
+      // as opposed to each individual varargs param.
+      return invokeWithArguments.invoke(handle, (Object) args);
+    }
+
+    @Override public String toString() {
+      return handle.toString();
+    }
+  }
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/Parameter.java b/extensions/assistedinject/src/com/google/inject/assistedinject/Parameter.java
new file mode 100644
index 0000000..717d29c
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/Parameter.java
@@ -0,0 +1,165 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.inject.ConfigurationException;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.internal.Annotations;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * Models a method or constructor parameter.
+ *
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class Parameter {
+  
+  private final Type type;
+  private final boolean isAssisted;
+  private final Annotation bindingAnnotation;
+  private final boolean isProvider;
+
+  private volatile Provider<? extends Object> provider;
+
+  public Parameter(Type type, Annotation[] annotations) {
+    this.type = type;
+    this.bindingAnnotation = getBindingAnnotation(annotations);
+    this.isAssisted = hasAssistedAnnotation(annotations);
+    this.isProvider = isProvider(type);
+  }
+
+  public boolean isProvidedByFactory() {
+    return isAssisted;
+  }
+  
+  public Type getType() {
+    return type;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    if (isAssisted) {
+      result.append("@Assisted ");
+    }
+    if (bindingAnnotation != null) {
+      result.append(bindingAnnotation).append(" ");
+    }
+    return result.append(type).toString();
+  }
+
+  private boolean hasAssistedAnnotation(Annotation[] annotations) {
+    for (Annotation annotation : annotations) {
+      if (annotation.annotationType().equals(Assisted.class)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Returns the Guice {@link Key} for this parameter.
+   */
+  public Object getValue(Injector injector) {
+    if (null == provider) {
+      synchronized (this) {
+        if (null == provider) {
+          provider = isProvider
+              ? injector.getProvider(getBindingForType(getProvidedType(type)))
+              : injector.getProvider(getPrimaryBindingKey());
+        }
+      }
+    }
+
+    return isProvider ? provider : provider.get();
+  }
+
+  public boolean isBound(Injector injector) {
+    return isBound(injector, getPrimaryBindingKey())
+        || isBound(injector, fixAnnotations(getPrimaryBindingKey()));
+  }
+
+  private boolean isBound(Injector injector, Key<?> key) {
+    // This method is particularly lame - we really need an API that can test
+    // for any binding, implicit or explicit
+    try {
+      return injector.getBinding(key) != null;
+    } catch (ConfigurationException e) {
+      return false;
+    }
+  }
+
+  /**
+   * Replace annotation instances with annotation types, this is only
+   * appropriate for testing if a key is bound and not for injecting.
+   *
+   * See Guice bug 125,
+   * https://github.com/google/guice/issues/125
+   */
+  public Key<?> fixAnnotations(Key<?> key) {
+    return key.getAnnotation() == null
+        ? key
+        : Key.get(key.getTypeLiteral(), key.getAnnotation().annotationType());
+  }
+
+  Key<?> getPrimaryBindingKey() {
+    return isProvider
+        ? getBindingForType(getProvidedType(type))
+        : getBindingForType(type);
+  }
+
+  private Type getProvidedType(Type type) {
+    return ((ParameterizedType) type).getActualTypeArguments()[0];
+  }
+
+  private boolean isProvider(Type type) {
+    return type instanceof ParameterizedType
+        && ((ParameterizedType) type).getRawType() == Provider.class;
+  }
+
+  private Key<?> getBindingForType(Type type) {
+    return bindingAnnotation != null
+        ? Key.get(type, bindingAnnotation)
+        : Key.get(type);
+  }
+
+  /**
+   * Returns the unique binding annotation from the specified list, or
+   * {@code null} if there are none.
+   *
+   * @throws IllegalStateException if multiple binding annotations exist.
+   */
+  private Annotation getBindingAnnotation(Annotation[] annotations) {
+    Annotation bindingAnnotation = null;
+    for (Annotation annotation : annotations) {
+      if (Annotations.isBindingAnnotation(annotation.annotationType())) {
+        checkArgument(bindingAnnotation == null,
+            "Parameter has multiple binding annotations: %s and %s", bindingAnnotation, annotation);
+        bindingAnnotation = annotation;
+      }
+    }
+    return bindingAnnotation;
+  }
+}
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/ParameterListKey.java b/extensions/assistedinject/src/com/google/inject/assistedinject/ParameterListKey.java
new file mode 100644
index 0000000..332b11d
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/ParameterListKey.java
@@ -0,0 +1,66 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import com.google.inject.TypeLiteral;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A list of {@link TypeLiteral}s to match an injectable Constructor's assited
+ * parameter types to the corresponding factory method.
+ *
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class ParameterListKey {
+  
+  private final List<Type> paramList;
+  
+  public ParameterListKey(List<Type> paramList) {
+    this.paramList = new ArrayList<Type>(paramList);
+  }
+  
+  public ParameterListKey(Type[] types) {
+    this(Arrays.asList(types));
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (!(o instanceof ParameterListKey)) {
+      return false;
+    }
+    ParameterListKey other = (ParameterListKey) o;
+    return paramList.equals(other.paramList);
+  }
+  
+  @Override
+  public int hashCode() {
+    return paramList.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return paramList.toString();
+  }
+}
\ No newline at end of file
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/package-info.java b/extensions/assistedinject/src/com/google/inject/assistedinject/package-info.java
new file mode 100644
index 0000000..9fc5b3e
--- /dev/null
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Extension for combining factory interfaces with injection; this extension requires {@code
+ * guice-assistedinject.jar}.
+ */
+package com.google.inject.assistedinject;
diff --git a/extensions/assistedinject/test/com/google/inject/assistedinject/ExtensionSpiTest.java b/extensions/assistedinject/test/com/google/inject/assistedinject/ExtensionSpiTest.java
new file mode 100644
index 0000000..051a50f
--- /dev/null
+++ b/extensions/assistedinject/test/com/google/inject/assistedinject/ExtensionSpiTest.java
@@ -0,0 +1,210 @@
+/**
+ * Copyright (C) 2010 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.inject.assistedinject;
+
+import static com.google.inject.name.Names.named;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Stage;
+import com.google.inject.name.Named;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Tests for AssistedInject Spi.
+ *
+ * @author ramakrishna@google.com (Ramakrishna Rajanna)
+ */
+public class ExtensionSpiTest extends TestCase {
+
+  public final void testSpiOnElements() throws Exception {
+    AssistedInjectSpiVisitor visitor = new AssistedInjectSpiVisitor();
+    Integer count = 0;
+    for(Element element : Elements.getElements(new Module())) {
+      if(element instanceof Binding) {
+        assertEquals(count++, ((Binding<?>)element).acceptTargetVisitor(visitor));
+      }
+    }
+    validateVisitor(visitor);
+  }
+
+  public void testSpiOnVisitor() throws Exception {
+    AssistedInjectSpiVisitor visitor = new AssistedInjectSpiVisitor();
+    Integer count = 0;
+    Injector injector = Guice.createInjector(new Module());
+    for(Binding<?> binding : injector.getBindings().values()) {
+      assertEquals(count++, binding.acceptTargetVisitor(visitor));
+    }
+    validateVisitor(visitor);
+  }
+
+  private void validateVisitor(AssistedInjectSpiVisitor visitor) throws Exception {
+    assertEquals(1, visitor.assistedBindingCount);
+    List<AssistedMethod> assistedMethods =
+        Lists.newArrayList(Iterables.getOnlyElement(
+            visitor.assistedInjectBindings).getAssistedMethods());
+    assertEquals(7, assistedMethods.size());
+    assertEquals(1, visitor.assistedBindingCount);
+    assertEquals(1, visitor.assistedInjectBindings.size());
+
+    // Validate for each of the methods in AnimalFactory
+    
+    Set<String> names = Sets.newHashSet();
+    for (AssistedMethod method : assistedMethods) {
+      String name = method.getFactoryMethod().getName();
+      names.add(name);
+      if (name.equals("createAStrangeCatAsAnimal")) {        
+        validateAssistedMethod(method, name, StrangeCat.class, ImmutableList.<Key<?>>of());        
+      } else if (name.equals("createStrangeCatWithConstructorForOwner")) {
+        validateAssistedMethod(method, name, StrangeCat.class, ImmutableList.<Key<?>>of());     
+      } else if (name.equals("createStrangeCatWithConstructorForAge")) {
+        validateAssistedMethod(method, name, StrangeCat.class, ImmutableList.<Key<?>>of());        
+      } else if (name.equals("createCatWithANonAssistedDependency")) {
+        validateAssistedMethod(method, name, CatWithAName.class,
+            ImmutableList.<Key<?>>of(Key.get(String.class, named("catName2"))));        
+      } else if (name.equals("createCat")) {
+        validateAssistedMethod(method, name, Cat.class, ImmutableList.<Key<?>>of());        
+      } else if (name.equals("createASimpleCatAsAnimal")) {
+        validateAssistedMethod(method, name, SimpleCat.class, ImmutableList.<Key<?>>of());
+      } else if (name.equals("createCatWithNonAssistedDependencies")) {
+        List<Key<?>> dependencyKeys = ImmutableList.<Key<?>>of(
+            Key.get(String.class, named("catName1")),
+            Key.get(String.class, named("petName")),        
+            Key.get(Integer.class, named("age")));
+        validateAssistedMethod(method, name, ExplodingCat.class, dependencyKeys);        
+      } else {
+        fail("Invalid method: " + method);
+      }
+    }
+    assertEquals(names, ImmutableSet.of("createAStrangeCatAsAnimal",
+        "createStrangeCatWithConstructorForOwner",
+        "createStrangeCatWithConstructorForAge",
+        "createCatWithANonAssistedDependency",
+        "createCat",
+        "createASimpleCatAsAnimal",
+        "createCatWithNonAssistedDependencies"));
+  }
+
+  private void validateAssistedMethod(AssistedMethod assistedMethod, String factoryMethodName,
+                                      Class clazz, List<Key<?>> dependencyKeys){
+    assertEquals(factoryMethodName, assistedMethod.getFactoryMethod().getName());
+    assertEquals(clazz, assistedMethod.getImplementationConstructor().getDeclaringClass());
+    assertEquals(dependencyKeys.size(), assistedMethod.getDependencies().size());
+    for (Dependency<?> dependency : assistedMethod.getDependencies()) {
+      assertTrue(dependencyKeys.contains(dependency.getKey()));
+    }
+    assertEquals(clazz, assistedMethod.getImplementationType().getType());
+  }
+
+
+  interface AnimalFactory {
+    Cat createCat(String owner);
+    CatWithAName createCatWithANonAssistedDependency(String owner);
+    @Named("SimpleCat") Animal createASimpleCatAsAnimal(String owner);
+    Animal createAStrangeCatAsAnimal(String owner);
+    StrangeCat createStrangeCatWithConstructorForOwner(String owner);
+    StrangeCat createStrangeCatWithConstructorForAge(Integer age);
+    ExplodingCat createCatWithNonAssistedDependencies(String owner);
+  }
+
+  interface Animal {}
+
+  private static class Cat implements Animal {
+    @Inject Cat(@Assisted String owner) {}
+  }
+
+  private static class SimpleCat implements Animal {
+    @Inject SimpleCat(@Assisted String owner) {
+    }
+  }
+
+  private static class StrangeCat implements Animal {
+    @AssistedInject StrangeCat(@Assisted String owner) {}
+    @AssistedInject StrangeCat(@Assisted Integer age) {}
+  }
+
+  private static class ExplodingCat implements Animal {
+    @Inject public ExplodingCat(@Named("catName1") String name, @Assisted String owner,
+                                @Named("age") Integer age, @Named("petName") String petName) {}
+  }
+
+  private static class CatWithAName extends Cat {
+    @Inject CatWithAName(@Assisted String owner, @Named("catName2") String name) {
+      super(owner);
+    }
+  }
+
+  public class Module extends AbstractModule{
+    @Override
+    protected void configure() {
+      bind(String.class).annotatedWith(named("catName1")).toInstance("kitty1");
+      bind(String.class).annotatedWith(named("catName2")).toInstance("kitty2");
+      bind(String.class).annotatedWith(named("petName")).toInstance("pussy");
+      bind(Integer.class).annotatedWith(named("age")).toInstance(12);
+      install(new FactoryModuleBuilder()
+        .implement(Animal.class, StrangeCat.class)
+        .implement(Animal.class, named("SimpleCat"), SimpleCat.class)
+        .build(AnimalFactory.class));
+    }
+  }
+
+  public class AssistedInjectSpiVisitor extends DefaultBindingTargetVisitor<Object, Integer>
+      implements AssistedInjectTargetVisitor<Object, Integer>  {
+
+    private final Set<Class> allowedClasses = 
+      ImmutableSet.<Class> of(
+        Injector.class, Stage.class, Logger.class,
+        String.class, Integer.class);
+    
+    private int assistedBindingCount = 0;
+    private int currentCount = 0;
+    private List<AssistedInjectBinding<?>> assistedInjectBindings = Lists.newArrayList();
+
+    public Integer visit(AssistedInjectBinding assistedInjectBinding) {
+      assistedInjectBindings.add(assistedInjectBinding);
+      assistedBindingCount++;
+      return currentCount++;
+    }
+
+    @Override
+    protected Integer visitOther(Binding<? extends Object> binding) {
+      if(!allowedClasses.contains(binding.getKey().getTypeLiteral().getRawType())) {
+        throw new AssertionFailedError("invalid other binding: " + binding);
+      }
+      return currentCount++;
+    }
+  }
+}
diff --git a/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryModuleBuilderTest.java b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryModuleBuilderTest.java
new file mode 100644
index 0000000..e047495
--- /dev/null
+++ b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryModuleBuilderTest.java
@@ -0,0 +1,540 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.Message;
+
+import junit.framework.TestCase;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class FactoryModuleBuilderTest extends TestCase {
+  
+  private enum Color { BLUE, GREEN, RED, GRAY, BLACK }
+
+  public void testImplicitForwardingAssistedBindingFailsWithInterface() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(Car.class).to(Golf.class);
+          install(new FactoryModuleBuilder().build(ColoredCarFactory.class));
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertContains(
+          ce.getMessage(), "1) " + Car.class.getName() + " is an interface, not a concrete class.",
+          "Unable to create AssistedInject factory.",
+          "while locating " + Car.class.getName(),
+          "at " + ColoredCarFactory.class.getName() + ".create(");
+      assertEquals(1, ce.getErrorMessages().size());
+    }
+  }
+  
+  public void testImplicitForwardingAssistedBindingFailsWithAbstractClass() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(AbstractCar.class).to(ArtCar.class);
+          install(new FactoryModuleBuilder().build(ColoredAbstractCarFactory.class));
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertContains(
+          ce.getMessage(), "1) " + AbstractCar.class.getName() + " is abstract, not a concrete class.",
+          "Unable to create AssistedInject factory.",
+          "while locating " + AbstractCar.class.getName(),
+          "at " + ColoredAbstractCarFactory.class.getName() + ".create(");
+      assertEquals(1, ce.getErrorMessages().size());
+    }
+  }
+
+  public void testImplicitForwardingAssistedBindingCreatesNewObjects() {
+    final Mustang providedMustang = new Mustang(Color.BLUE);
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        install(new FactoryModuleBuilder().build(MustangFactory.class));
+      }
+      @Provides Mustang provide() { return providedMustang; }
+    });
+    assertSame(providedMustang, injector.getInstance(Mustang.class));
+    MustangFactory factory = injector.getInstance(MustangFactory.class);
+    Mustang created = factory.create(Color.GREEN);
+    assertNotSame(providedMustang, created);
+    assertEquals(Color.BLUE, providedMustang.color);
+    assertEquals(Color.GREEN, created.color);
+  }
+
+  public void testExplicitForwardingAssistedBindingFailsWithInterface() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(Volkswagen.class).to(Golf.class);
+          install(new FactoryModuleBuilder()
+            .implement(Car.class, Volkswagen.class)
+            .build(ColoredCarFactory.class));
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertContains(
+          ce.getMessage(), "1) " + Volkswagen.class.getName() + " is an interface, not a concrete class.",
+          "Unable to create AssistedInject factory.",
+          "while locating " + Volkswagen.class.getName(),
+          "while locating " + Car.class.getName(),
+          "at " + ColoredCarFactory.class.getName() + ".create(");
+      assertEquals(1, ce.getErrorMessages().size());
+    }
+  }
+
+  public void testExplicitForwardingAssistedBindingFailsWithAbstractClass() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(AbstractCar.class).to(ArtCar.class);
+          install(new FactoryModuleBuilder()
+            .implement(Car.class, AbstractCar.class)
+            .build(ColoredCarFactory.class));
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertContains(
+          ce.getMessage(), "1) " + AbstractCar.class.getName() + " is abstract, not a concrete class.",
+          "Unable to create AssistedInject factory.",
+          "while locating " + AbstractCar.class.getName(),
+          "while locating " + Car.class.getName(),
+          "at " + ColoredCarFactory.class.getName() + ".create(");
+      assertEquals(1, ce.getErrorMessages().size());
+    }
+  }
+  
+  public void testExplicitForwardingAssistedBindingCreatesNewObjects() {
+    final Mustang providedMustang = new Mustang(Color.BLUE);
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        install(new FactoryModuleBuilder().implement(Car.class, Mustang.class).build(
+            ColoredCarFactory.class));
+      }
+      @Provides Mustang provide() { return providedMustang; }
+    });
+    assertSame(providedMustang, injector.getInstance(Mustang.class));
+    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
+    Mustang created = (Mustang)factory.create(Color.GREEN);
+    assertNotSame(providedMustang, created);
+    assertEquals(Color.BLUE, providedMustang.color);
+    assertEquals(Color.GREEN, created.color);
+  }
+
+  public void testAnnotatedAndParentBoundReturnValue() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(Car.class).to(Golf.class);
+
+        bind(Integer.class).toInstance(911);
+        bind(Double.class).toInstance(5.0d);
+        install(new FactoryModuleBuilder()
+            .implement(Car.class, Names.named("german"), Beetle.class)
+            .implement(Car.class, Names.named("american"), Mustang.class)
+            .build(AnnotatedVersatileCarFactory.class));
+      }
+    });
+
+    AnnotatedVersatileCarFactory factory = injector.getInstance(AnnotatedVersatileCarFactory.class);
+    assertTrue(factory.getGermanCar(Color.BLACK) instanceof Beetle);
+    assertTrue(injector.getInstance(Car.class) instanceof Golf);
+  }
+
+  public void testParentBoundReturnValue() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(Car.class).to(Golf.class);
+        bind(Double.class).toInstance(5.0d);
+        install(new FactoryModuleBuilder()
+            .implement(Car.class, Mustang.class)
+            .build(ColoredCarFactory.class));
+      }
+    });
+
+    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
+    assertTrue(factory.create(Color.RED) instanceof Mustang);
+    assertTrue(injector.getInstance(Car.class) instanceof Golf);
+  }
+
+  public void testConfigureAnnotatedReturnValue() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        install(new FactoryModuleBuilder()
+            .implement(Car.class, Names.named("german"), Beetle.class)
+            .implement(Car.class, Names.named("american"), Mustang.class)
+            .build(AnnotatedVersatileCarFactory.class));
+      }
+    });
+
+    AnnotatedVersatileCarFactory factory = injector.getInstance(AnnotatedVersatileCarFactory.class);
+    assertTrue(factory.getGermanCar(Color.GRAY) instanceof Beetle);
+    assertTrue(factory.getAmericanCar(Color.BLACK) instanceof Mustang);
+  }
+
+  public void testNoBindingAssistedInject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder().build(MustangFactory.class));
+      }
+    });
+
+    MustangFactory factory = injector.getInstance(MustangFactory.class);
+
+    Mustang mustang = factory.create(Color.BLUE);
+    assertEquals(Color.BLUE, mustang.color);
+  }
+
+  public void testBindingAssistedInject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder()
+            .implement(Car.class, Mustang.class)
+            .build(ColoredCarFactory.class));
+      }
+    });
+
+    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
+
+    Mustang mustang = (Mustang) factory.create(Color.BLUE);
+    assertEquals(Color.BLUE, mustang.color);
+  }
+
+  public void testDuplicateBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder()
+            .implement(Car.class, Mustang.class)
+            .build(ColoredCarFactory.class));
+        install(new FactoryModuleBuilder()
+            .implement(Car.class, Mustang.class)
+            .build(ColoredCarFactory.class));
+      }
+    });
+
+    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
+
+    Mustang mustang = (Mustang) factory.create(Color.BLUE);
+    assertEquals(Color.BLUE, mustang.color);
+  }
+
+  public void testSimilarBindingsWithConflictingImplementations() {
+    try {
+      Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new FactoryModuleBuilder()
+              .implement(Car.class, Mustang.class)
+              .build(ColoredCarFactory.class));
+          install(new FactoryModuleBuilder()
+              .implement(Car.class, Golf.class)
+              .build(ColoredCarFactory.class));
+        }
+      });
+      injector.getInstance(ColoredCarFactory.class);
+      fail();
+    } catch (CreationException ce) {
+      assertContains(ce.getMessage(),
+          "A binding to " + ColoredCarFactory.class.getName() + " was already configured");
+      assertEquals(1, ce.getErrorMessages().size());
+    }
+  }
+
+  public void testMultipleReturnTypes() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        install(new FactoryModuleBuilder().build(VersatileCarFactory.class));
+      }
+    });
+
+    VersatileCarFactory factory = injector.getInstance(VersatileCarFactory.class);
+
+    Mustang mustang = factory.getMustang(Color.RED);
+    assertEquals(Color.RED, mustang.color);
+
+    Beetle beetle = factory.getBeetle(Color.GREEN);
+    assertEquals(Color.GREEN, beetle.color);
+  }
+  
+  public void testParameterizedClassesWithNoImplements() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder().build(new TypeLiteral<Foo.Factory<String>>() {}));
+      }
+    });
+    
+    Foo.Factory<String> factory = injector.getInstance(Key.get(new TypeLiteral<Foo.Factory<String>>() {}));
+    @SuppressWarnings("unused")
+    Foo<String> foo = factory.create(new Bar());
+  }
+  
+  public void testGenericErrorMessageMakesSense() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+         install(new FactoryModuleBuilder().build(Key.get(Foo.Factory.class))); 
+        }
+      });
+      fail();
+    } catch(CreationException ce ) {
+      // Assert not only that it's the correct message, but also that it's the *only* message.
+      Collection<Message> messages = ce.getErrorMessages();
+      assertEquals(
+          Foo.Factory.class.getName() + " cannot be used as a key; It is not fully specified.", 
+          Iterables.getOnlyElement(messages).getMessage());
+    }
+  }
+
+  interface Car {}
+
+  interface Volkswagen extends Car {}
+
+  interface ColoredCarFactory {
+    Car create(Color color);
+  }
+
+  interface MustangFactory {
+    Mustang create(Color color);
+  }
+
+  interface VersatileCarFactory {
+    Mustang getMustang(Color color);
+    Beetle getBeetle(Color color);
+  }
+
+  interface AnnotatedVersatileCarFactory {
+    @Named("german") Car getGermanCar(Color color);
+    @Named("american") Car getAmericanCar(Color color);
+  }
+
+  public static class Golf implements Volkswagen {}
+
+  public static class Mustang implements Car {
+    private final Color color;
+    @Inject
+    public Mustang(@Assisted Color color) {
+      this.color = color;
+    }
+  }
+
+  public static class Beetle implements Car {
+    private final Color color;
+    @Inject
+    public Beetle(@Assisted Color color) {
+      this.color = color;
+    }
+  }
+  
+  public static class Foo<E> {
+    static interface Factory<E> {
+      Foo<E> create(Bar bar);
+    }
+    @SuppressWarnings("unused")
+    @Inject Foo(@Assisted Bar bar, Baz<E> baz) {}
+  }
+  
+  public static class Bar {}
+  @SuppressWarnings("unused")
+  public static class Baz<E> {}
+  
+  abstract static class AbstractCar implements Car {}  
+  interface ColoredAbstractCarFactory {
+    AbstractCar create(Color color);
+  }  
+  public static class ArtCar extends AbstractCar {}
+    
+  public void testFactoryBindingDependencies() {
+    // validate dependencies work in all stages & as a raw element,
+    // and that dependencies work for methods, fields, constructors,
+    // and for @AssistedInject constructors too.
+    Module module = new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Integer.class).toInstance(42);
+        bind(Double.class).toInstance(4.2d);
+        bind(Float.class).toInstance(4.2f);
+        bind(String.class).annotatedWith(named("dog")).toInstance("dog");
+        bind(String.class).annotatedWith(named("cat1")).toInstance("cat1");
+        bind(String.class).annotatedWith(named("cat2")).toInstance("cat2");
+        bind(String.class).annotatedWith(named("cat3")).toInstance("cat3");
+        bind(String.class).annotatedWith(named("arbitrary")).toInstance("fail!");
+        install(new FactoryModuleBuilder()
+                .implement(Animal.class, Dog.class)
+                .build(AnimalHouse.class));
+      }
+    };
+
+    Set<Key<?>> expectedKeys = ImmutableSet.<Key<?>>of(
+        Key.get(Integer.class),
+        Key.get(Double.class),
+        Key.get(Float.class),
+        Key.get(String.class, named("dog")),
+        Key.get(String.class, named("cat1")),
+        Key.get(String.class, named("cat2")),
+        Key.get(String.class, named("cat3"))
+    );
+    
+    Injector injector = Guice.createInjector(module);
+    validateDependencies(expectedKeys, injector.getBinding(AnimalHouse.class));
+    
+    injector = Guice.createInjector(Stage.TOOL, module);
+    validateDependencies(expectedKeys, injector.getBinding(AnimalHouse.class));
+    
+    List<Element> elements = Elements.getElements(module);
+    boolean found = false;
+    for(Element element : elements) {
+      if(element instanceof Binding) {
+        Binding<?> binding = (Binding<?>) element;
+        if(binding.getKey().equals(Key.get(AnimalHouse.class))) {
+          found = true;
+          validateDependencies(expectedKeys, binding);
+          break;
+        }
+      }
+    }
+    assertTrue(found);
+  }
+  
+  private void validateDependencies(Set<Key<?>> expectedKeys, Binding<?> binding) {
+    Set<Dependency<?>> dependencies = ((HasDependencies)binding).getDependencies();
+    Set<Key<?>> actualKeys = new HashSet<Key<?>>();
+    for (Dependency<?> dependency : dependencies) {
+      actualKeys.add(dependency.getKey());
+    }
+    assertEquals(expectedKeys, actualKeys);
+  }
+  
+  interface AnimalHouse {
+    Animal createAnimal(String name);
+    Cat createCat(String name);
+    Cat createCat(int age);
+  }
+  
+  interface Animal {}
+  @SuppressWarnings("unused")
+  private static class Dog implements Animal {
+    @Inject int a;
+    @Inject Dog(@Assisted String a, double b) {}
+    @Inject void register(@Named("dog") String a) {}
+  }
+  @SuppressWarnings("unused")
+  private static class Cat implements Animal {
+    @Inject float a;
+    @AssistedInject Cat(@Assisted String a, @Named("cat1") String b) {}
+    @AssistedInject Cat(@Assisted int a, @Named("cat2") String b) {}
+    @AssistedInject Cat(@Assisted byte a, @Named("catfail") String b) {} // not a dependency!
+    @Inject void register(@Named("cat3") String a) {}
+  }
+  
+  public void testFactoryPublicAndReturnTypeNotPublic() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new FactoryModuleBuilder()
+              .implement(Hidden.class, HiddenImpl.class)
+              .build(NotHidden.class));
+        }
+      });
+    } catch(CreationException ce) {
+      assertEquals(NotHidden.class.getName() + " is public, but has a method that returns a non-public type: "
+          + Hidden.class.getName() + ". Due to limitations with java.lang.reflect.Proxy, this is not allowed. "
+          + "Please either make the factory non-public or the return type public.",           
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  interface Hidden {}
+  public static class HiddenImpl implements Hidden {}
+  public interface NotHidden {
+    Hidden create();
+  }
+  
+  public void testSingletonScopeOnAssistedClassIsIgnored() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new FactoryModuleBuilder().build(SingletonFactory.class));
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      assertEquals("Found scope annotation [" + Singleton.class.getName() + "]"
+          + " on implementation class [" + AssistedSingleton.class.getName() + "]"
+          + " of AssistedInject factory [" + SingletonFactory.class.getName() + "]."
+          + "\nThis is not allowed, please remove the scope annotation.",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  interface SingletonFactory {
+    AssistedSingleton create(String string);
+  }
+
+  @SuppressWarnings("GuiceAssistedInjectScoping")
+  @Singleton
+  static class AssistedSingleton {
+    @Inject
+    public AssistedSingleton(@SuppressWarnings("unused") @Assisted String string) {
+    }
+  }
+  
+}
diff --git a/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProvider2Test.java b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProvider2Test.java
new file mode 100644
index 0000000..c0e9bbd
--- /dev/null
+++ b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProvider2Test.java
@@ -0,0 +1,1220 @@
+/**
+ * Copyright (C) 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.inject.assistedinject;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.assertEqualsBothWays;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.ConfigurationException;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.assistedinject.FactoryProvider2Test.Equals.ComparisonMethod;
+import com.google.inject.assistedinject.FactoryProvider2Test.Equals.Impl;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@SuppressWarnings("deprecation")
+public class FactoryProvider2Test extends TestCase {
+
+  private enum Color { BLUE, GREEN, RED, GRAY, BLACK, ORANGE, PINK }
+  
+  public void testAssistedFactory() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE);
+    assertEquals(Color.BLUE, blueMustang.color);
+    assertEquals(5.0d, blueMustang.engineSize);
+
+    Mustang redMustang = (Mustang) carFactory.create(Color.RED);
+    assertEquals(Color.RED, redMustang.color);
+    assertEquals(5.0d, redMustang.engineSize);
+  }
+
+  public void testAssistedFactoryWithAnnotations() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
+        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Camaro.class));
+      }
+    });
+
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Camaro blueCamaro = (Camaro) carFactory.create(Color.BLUE);
+    assertEquals(Color.BLUE, blueCamaro.color);
+    assertEquals(1984, blueCamaro.modelYear);
+    assertEquals(250, blueCamaro.horsePower);
+
+    Camaro redCamaro = (Camaro) carFactory.create(Color.RED);
+    assertEquals(Color.RED, redCamaro.color);
+    assertEquals(1984, redCamaro.modelYear);
+    assertEquals(250, redCamaro.horsePower);
+  }
+
+  public interface Car {}
+
+  interface ColoredCarFactory {
+    Car create(Color color);
+  }
+
+  public static class Mustang implements Car {
+    private final double engineSize;
+    private final Color color;
+
+    @Inject
+    public Mustang(double engineSize, @Assisted Color color) {
+      this.engineSize = engineSize;
+      this.color = color;
+    }
+
+    public void drive() {}
+  }
+
+  public static class Camaro implements Car {
+    private final int horsePower;
+    private final int modelYear;
+    private final Color color;
+
+    @Inject
+    public Camaro(
+        @Named("horsePower") int horsePower,
+        @Named("modelYear") int modelYear,
+        @Assisted Color color) {
+      this.horsePower = horsePower;
+      this.modelYear = modelYear;
+      this.color = color;
+    }
+  }
+
+  interface SummerCarFactory {
+    Car create(Color color, boolean convertable);
+  }
+
+  public void testFactoryUsesInjectedConstructor() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(float.class).toInstance(140f);
+        bind(SummerCarFactory.class).toProvider(
+            FactoryProvider.newFactory(SummerCarFactory.class, Corvette.class));
+      }
+    });
+
+    SummerCarFactory carFactory = injector.getInstance(SummerCarFactory.class);
+
+    Corvette redCorvette = (Corvette) carFactory.create(Color.RED, false);
+    assertEquals(Color.RED, redCorvette.color);
+    assertEquals(140f, redCorvette.maxMph);
+    assertFalse(redCorvette.isConvertable);
+  }
+
+  public static class Corvette implements Car {
+    private boolean isConvertable;
+    private Color color;
+    private float maxMph;
+
+    @SuppressWarnings("unused")
+    public Corvette(Color color, boolean isConvertable) {
+      throw new IllegalStateException("Not an @AssistedInject constructor");
+    }
+
+    @Inject
+    public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertable) {
+      this.isConvertable = isConvertable;
+      this.color = color;
+      this.maxMph = maxMph;
+    }
+  }
+
+  public void testConstructorDoesntNeedAllFactoryMethodArguments() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(SummerCarFactory.class).toProvider(
+            FactoryProvider.newFactory(SummerCarFactory.class, Beetle.class));
+      }
+    });
+    SummerCarFactory factory = injector.getInstance(SummerCarFactory.class);
+
+    Beetle beetle = (Beetle) factory.create(Color.RED, true);
+    assertSame(Color.RED, beetle.color);
+  }
+
+  public static class Beetle implements Car {
+    private final Color color;
+    @Inject
+    public Beetle(@Assisted Color color) {
+      this.color = color;
+    }
+  }
+
+  public void testMethodsAndFieldsGetInjected() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("turbo");
+        bind(int.class).toInstance(911);
+        bind(double.class).toInstance(50000d);
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Porsche.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Porsche grayPorsche = (Porsche) carFactory.create(Color.GRAY);
+    assertEquals(Color.GRAY, grayPorsche.color);
+    assertEquals(50000d, grayPorsche.price);
+    assertEquals(911, grayPorsche.model);
+    assertEquals("turbo", grayPorsche.name);
+  }
+
+  public static class Porsche implements Car {
+    private final Color color;
+    private final double price;
+    private @Inject String name;
+    private int model;
+
+    @Inject
+    public Porsche(@Assisted Color color, double price) {
+      this.color = color;
+      this.price = price;
+    }
+
+    @Inject void setModel(int model) {
+      this.model = model;
+    }
+  }
+
+  public void testProviderInjection() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("trans am");
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Firebird.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Firebird blackFirebird = (Firebird) carFactory.create(Color.BLACK);
+    assertEquals(Color.BLACK, blackFirebird.color);
+    assertEquals("trans am", blackFirebird.modifiersProvider.get());
+  }
+
+  public static class Firebird implements Car {
+    private final Provider<String> modifiersProvider;
+    private final Color color;
+
+    @Inject
+    public Firebird(Provider<String> modifiersProvider, @Assisted Color color) {
+      this.modifiersProvider = modifiersProvider;
+      this.color = color;
+    }
+  }
+  
+  public void testAssistedProviderInjection() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("trans am");
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Flamingbird.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Flamingbird flamingbird = (Flamingbird) carFactory.create(Color.BLACK);
+    assertEquals(Color.BLACK, flamingbird.colorProvider.get());
+    assertEquals("trans am", flamingbird.modifiersProvider.get());
+    
+    Flamingbird flamingbird2 = (Flamingbird) carFactory.create(Color.RED);
+    assertEquals(Color.RED, flamingbird2.colorProvider.get());
+    assertEquals("trans am", flamingbird2.modifiersProvider.get());
+    // Make sure the original flamingbird is black still.
+    assertEquals(Color.BLACK, flamingbird.colorProvider.get());
+  }  
+  
+  public static class Flamingbird implements Car {
+    private final Provider<String> modifiersProvider;
+    private final Provider<Color> colorProvider;
+
+    @Inject
+    public Flamingbird(Provider<String> modifiersProvider, @Assisted Provider<Color> colorProvider) {
+      this.modifiersProvider = modifiersProvider;
+      this.colorProvider = colorProvider;
+    }
+  }
+
+  public void testTypeTokenInjection() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(new TypeLiteral<Set<String>>() {}).toInstance(Collections.singleton("Flux Capacitor"));
+        bind(new TypeLiteral<Set<Integer>>() {}).toInstance(Collections.singleton(88));
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, DeLorean.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    DeLorean deLorean = (DeLorean) carFactory.create(Color.GRAY);
+    assertEquals(Color.GRAY, deLorean.color);
+    assertEquals("Flux Capacitor", deLorean.features.iterator().next());
+    assertEquals(new Integer(88), deLorean.featureActivationSpeeds.iterator().next());
+  }
+
+  public static class DeLorean implements Car {
+    private final Set<String> features;
+    private final Set<Integer> featureActivationSpeeds;
+    private final Color color;
+
+    @Inject
+    public DeLorean(
+        Set<String> extraFeatures, Set<Integer> featureActivationSpeeds, @Assisted Color color) {
+      this.features = extraFeatures;
+      this.featureActivationSpeeds = featureActivationSpeeds;
+      this.color = color;
+    }
+  }
+
+  public void testTypeTokenProviderInjection() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(new TypeLiteral<Set<String>>() { }).toInstance(Collections.singleton("Datsun"));
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Z.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Z orangeZ = (Z) carFactory.create(Color.ORANGE);
+    assertEquals(Color.ORANGE, orangeZ.color);
+    assertEquals("Datsun", orangeZ.manufacturersProvider.get().iterator().next());
+  }
+
+  public static class Z implements Car {
+    private final Provider<Set<String>> manufacturersProvider;
+    private final Color color;
+
+    @Inject
+    public Z(Provider<Set<String>> manufacturersProvider, @Assisted Color color) {
+      this.manufacturersProvider = manufacturersProvider;
+      this.color = color;
+    }
+  }
+
+  public static class Prius implements Car {
+    final Color color;
+
+    @Inject
+    private Prius(@Assisted Color color) {
+      this.color = color;
+    }
+  }
+
+  public void testAssistInjectionInNonPublicConstructor() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Prius.class));
+      }
+    });
+    Prius prius = (Prius) injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE);
+    assertEquals(prius.color, Color.ORANGE);
+  }
+
+  public static class ExplodingCar implements Car {
+    @Inject
+    public ExplodingCar(@SuppressWarnings("unused") @Assisted Color color) {
+      throw new IllegalStateException("kaboom!");
+    }
+  }
+
+  public void testExceptionDuringConstruction() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, ExplodingCar.class));
+      }
+    });
+    try {
+      injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE);
+      fail();
+    } catch (IllegalStateException e) {
+      assertEquals("kaboom!", e.getMessage());
+    }
+  }
+
+  public static class DefectiveCar implements Car {
+    @Inject
+    public DefectiveCar() throws ExplosionException {
+      throw new ExplosionException();
+    }
+  }
+
+  public static class ExplosionException extends Exception { }
+  public static class FireException extends Exception { }
+
+  public interface DefectiveCarFactoryWithNoExceptions {
+    Car createCar();
+  }
+
+  public interface DefectiveCarFactory {
+    Car createCar() throws FireException;
+  }
+
+  public interface CorrectDefectiveCarFactory {
+    Car createCar() throws FireException, ExplosionException;
+  }
+
+  public void testConstructorExceptionsAreThrownByFactory() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(CorrectDefectiveCarFactory.class).toProvider(
+            FactoryProvider.newFactory(CorrectDefectiveCarFactory.class, DefectiveCar.class));
+      }
+    });
+    try {
+      injector.getInstance(CorrectDefectiveCarFactory.class).createCar();
+      fail();
+    } catch (FireException e) {
+      fail();
+    } catch (ExplosionException expected) {
+    }
+  }
+
+  public static class WildcardCollection {
+
+    public interface Factory {
+      WildcardCollection create(Collection<?> items);
+    }
+
+    @Inject
+    public WildcardCollection(@SuppressWarnings("unused") @Assisted Collection<?> items) { }
+  }
+
+  public void testWildcardGenerics() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(WildcardCollection.Factory.class).toProvider(
+            FactoryProvider.newFactory(WildcardCollection.Factory.class, WildcardCollection.class));
+      }
+    });
+    WildcardCollection.Factory factory = injector.getInstance(WildcardCollection.Factory.class);
+    factory.create(Collections.emptyList());
+  }
+
+  public static class SteeringWheel {}
+
+  public static class Fiat implements Car {
+    private final SteeringWheel steeringWheel;
+    private final Color color;
+
+    @Inject
+    public Fiat(SteeringWheel steeringWheel, @Assisted Color color) {
+      this.steeringWheel = steeringWheel;
+      this.color = color;
+    }
+  }
+
+  public void testFactoryWithImplicitBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Fiat.class));
+      }
+    });
+
+    ColoredCarFactory coloredCarFactory = injector.getInstance(ColoredCarFactory.class);
+    Fiat fiat = (Fiat) coloredCarFactory.create(Color.GREEN);
+    assertEquals(Color.GREEN, fiat.color);
+    assertNotNull(fiat.steeringWheel);
+  }
+
+  public void testFactoryFailsWithMissingBinding() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(ColoredCarFactory.class).toProvider(
+              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Could not find a suitable constructor in java.lang.Double.",
+          "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java");
+    }
+  }
+  
+  public void testFactoryFailsWithMissingBindingInToolStage() {
+    try {
+      Guice.createInjector(Stage.TOOL, new AbstractModule() {
+        @Override protected void configure() {
+          bind(ColoredCarFactory.class).toProvider(
+              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Could not find a suitable constructor in java.lang.Double.",
+          "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java");
+    }
+  }
+
+  public void testMethodsDeclaredInObject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(Double.class).toInstance(5.0d);
+          bind(ColoredCarFactory.class).toProvider(
+              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+        }
+      });
+
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    assertEqualsBothWays(carFactory, carFactory);
+  }
+
+  static class Subaru implements Car {
+    @Inject @Assisted Provider<Color> colorProvider;
+  }
+
+  public void testInjectingProviderOfParameter() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(ColoredCarFactory.class).toProvider(
+              FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class));
+        }
+      });
+
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+    Subaru subaru = (Subaru) carFactory.create(Color.RED);
+
+    assertSame(Color.RED, subaru.colorProvider.get());
+    assertSame(Color.RED, subaru.colorProvider.get());
+    
+    Subaru sedan  = (Subaru) carFactory.create(Color.BLUE);
+    assertSame(Color.BLUE, sedan.colorProvider.get());
+    assertSame(Color.BLUE, sedan.colorProvider.get());
+    
+    // and make sure the subaru is still red
+    assertSame(Color.RED, subaru.colorProvider.get());
+  }
+
+  public void testInjectingNullParameter() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(ColoredCarFactory.class).toProvider(
+              FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class));
+        }
+      });
+
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+    Subaru subaru = (Subaru) carFactory.create(null);
+
+    assertNull(subaru.colorProvider.get());
+    assertNull(subaru.colorProvider.get());
+  }
+
+  interface ProviderBasedColoredCarFactory {
+    Car createCar(Provider<Color> colorProvider, Provider<String> stringProvider);
+    Mustang createMustang(@Assisted("color") Provider<Color> colorProvider);
+  }
+
+  public void testAssistedProviderIsDisallowed() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+          @Override protected void configure() {
+            bind(ProviderBasedColoredCarFactory.class).toProvider(
+                FactoryProvider.newFactory(ProviderBasedColoredCarFactory.class, Subaru.class));
+          }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size());
+      // Assert each method individually, because JDK7 doesn't guarantee method ordering.
+      assertContains(expected.getMessage(),
+          ") A Provider may not be a type in a factory method of an AssistedInject."
+            + "\n  Offending instance is parameter [1] with key"
+            + " [com.google.inject.Provider<" + Color.class.getName() + ">] on method ["
+            + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
+      assertContains(expected.getMessage(),
+          ") A Provider may not be a type in a factory method of an AssistedInject."
+            + "\n  Offending instance is parameter [2] with key"
+            + " [com.google.inject.Provider<java.lang.String>] on method ["
+            + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
+      assertContains(expected.getMessage(),
+          ") A Provider may not be a type in a factory method of an AssistedInject."
+            + "\n  Offending instance is parameter [1] with key"
+            + " [com.google.inject.Provider<" + Color.class.getName() + ">"
+            + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
+            + " on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
+      );
+      assertContains(expected.getMessage(),
+          ") No implementation for com.google.inject.assistedinject."
+            + "FactoryProvider2Test$ProviderBasedColoredCarFactory was bound.");
+    }
+  }
+
+  interface JavaxProviderBasedColoredCarFactory {
+    Car createCar(javax.inject.Provider<Color> colorProvider, javax.inject.Provider<String> stringProvider);
+    Mustang createMustang(@Assisted("color") javax.inject.Provider<Color> colorProvider);
+  }
+
+  public void testAssistedJavaxProviderIsDisallowed() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+          @Override protected void configure() {
+            bind(JavaxProviderBasedColoredCarFactory.class).toProvider(
+                FactoryProvider.newFactory(JavaxProviderBasedColoredCarFactory.class, Subaru.class));
+          }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size());
+      assertContains(expected.getMessage(),
+          ") A Provider may not be a type in a factory method of an AssistedInject."
+            + "\n  Offending instance is parameter [1] with key"
+            + " [com.google.inject.Provider<" + Color.class.getName() + ">] on method ["
+            + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
+      assertContains(expected.getMessage(),
+          ") A Provider may not be a type in a factory method of an AssistedInject."
+            + "\n  Offending instance is parameter [2] with key"
+            + " [com.google.inject.Provider<java.lang.String>] on method ["
+            + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
+      assertContains(expected.getMessage(),
+          ") A Provider may not be a type in a factory method of an AssistedInject."
+            + "\n  Offending instance is parameter [1] with key"
+            + " [com.google.inject.Provider<" + Color.class.getName() + ">"
+            + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
+            + " on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
+      );
+      assertContains(expected.getMessage(),
+          ") No implementation for com.google.inject.assistedinject."
+            + "FactoryProvider2Test$JavaxProviderBasedColoredCarFactory was bound.");
+    }
+  }
+
+  public void testFactoryUseBeforeInitialization() {
+    ColoredCarFactory carFactory = FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)
+        .get();
+    try {
+      carFactory.create(Color.RED);
+      fail();
+    } catch (IllegalStateException expected) {
+      assertContains(expected.getMessage(),
+          "Factories.create() factories cannot be used until they're initialized by Guice.");
+    }
+  }
+
+  interface MustangFactory {
+    Mustang create(Color color);
+  }
+
+  public void testFactoryBuildingConcreteTypes() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(double.class).toInstance(5.0d);
+        // note there is no 'thatMakes()' call here:
+        bind(MustangFactory.class).toProvider(
+            FactoryProvider.newFactory(MustangFactory.class, Mustang.class));
+      }
+    });
+    MustangFactory factory = injector.getInstance(MustangFactory.class);
+
+    Mustang mustang = factory.create(Color.RED);
+    assertSame(Color.RED, mustang.color);
+    assertEquals(5.0d, mustang.engineSize);
+  }
+
+  static class Fleet {
+    @Inject Mustang mustang;
+    @Inject Camaro camaro;
+  }
+
+  interface FleetFactory {
+    Fleet createFleet(Color color);
+  }
+
+  public void testInjectDeepIntoConstructedObjects() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(double.class).toInstance(5.0d);
+        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
+        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
+        bind(FleetFactory.class).toProvider(FactoryProvider.newFactory(FleetFactory.class,
+            Fleet.class));
+      }
+    });
+
+    FleetFactory fleetFactory = injector.getInstance(FleetFactory.class);
+    Fleet fleet = fleetFactory.createFleet(Color.RED);
+
+    assertSame(Color.RED, fleet.mustang.color);
+    assertEquals(5.0d, fleet.mustang.engineSize);
+    assertSame(Color.RED, fleet.camaro.color);
+    assertEquals(250, fleet.camaro.horsePower);
+    assertEquals(1984, fleet.camaro.modelYear);
+  }
+
+  interface TwoToneCarFactory {
+    Car create(@Assisted("paint") Color paint, @Assisted("fabric") Color fabric);
+  }
+
+  static class Maxima implements Car {
+    @Inject @Assisted("paint") Color paint;
+    @Inject @Assisted("fabric") Color fabric;
+  }
+
+  public void testDistinctKeys() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(TwoToneCarFactory.class).toProvider(
+            FactoryProvider.newFactory(TwoToneCarFactory.class, Maxima.class));
+      }
+    });
+
+    TwoToneCarFactory factory = injector.getInstance(TwoToneCarFactory.class);
+    Maxima maxima = (Maxima) factory.create(Color.BLACK, Color.GRAY);
+    assertSame(Color.BLACK, maxima.paint);
+    assertSame(Color.GRAY, maxima.fabric);
+  }
+
+  interface DoubleToneCarFactory {
+    Car create(@Assisted("paint") Color paint, @Assisted("paint") Color morePaint);
+  }
+
+  public void testDuplicateKeys() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(DoubleToneCarFactory.class).toProvider(
+              FactoryProvider.newFactory(DoubleToneCarFactory.class, Maxima.class));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "A binding to " + Color.class.getName() + " annotated with @"
+          + Assisted.class.getName() + "(value=paint) was already configured at");
+    }
+  }
+
+  /*if[AOP]*/
+  public void testMethodInterceptorsOnAssistedTypes() {
+    final AtomicInteger invocationCount = new AtomicInteger();
+    final org.aopalliance.intercept.MethodInterceptor interceptor
+        = new org.aopalliance.intercept.MethodInterceptor() {
+      public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation)
+          throws Throwable {
+        invocationCount.incrementAndGet();
+        return methodInvocation.proceed();
+      }
+    };
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.any(), interceptor);
+        bind(Double.class).toInstance(5.0d);
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+      }
+    });
+
+    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
+    Mustang mustang = (Mustang) factory.create(Color.GREEN);
+    assertEquals(0, invocationCount.get());
+    mustang.drive();
+    assertEquals(1, invocationCount.get());
+  }
+  /*end[AOP]*/
+
+  /**
+   * Our factories aren't reusable across injectors. Although this behaviour isn't something we
+   * like, I have a test case to make sure the error message is pretty.
+   */
+  public void testFactoryReuseErrorMessageIsPretty() {
+    final Provider<ColoredCarFactory> factoryProvider
+        = FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class);
+
+    Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        bind(ColoredCarFactory.class).toProvider(factoryProvider);
+      }
+    });
+
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(Double.class).toInstance(5.0d);
+          bind(ColoredCarFactory.class).toProvider(factoryProvider);
+        }
+      });
+      fail();
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Factories.create() factories may only be used in one Injector!");
+    }
+  }
+
+  public void testNonAssistedFactoryMethodParameter() {
+    try {
+      FactoryProvider.newFactory(NamedParameterFactory.class, Mustang.class);
+      fail();
+    } catch(ConfigurationException expected) {
+      assertContains(expected.getMessage(),
+          "Only @Assisted is allowed for factory parameters, but found @" + Named.class.getName());
+    }
+  }
+
+  interface NamedParameterFactory {
+    Car create(@Named("seats") int seats, double engineSize);
+  }
+
+
+  public void testDefaultAssistedAnnotation() throws NoSuchFieldException {
+    Assisted plainAssisted
+        = Subaru.class.getDeclaredField("colorProvider").getAnnotation(Assisted.class);
+    assertEqualsBothWays(FactoryProvider2.DEFAULT_ANNOTATION, plainAssisted);
+    assertEquals(FactoryProvider2.DEFAULT_ANNOTATION.toString(), plainAssisted.toString());
+  }
+
+  interface GenericColoredCarFactory<T extends Car> {
+    T create(Color color);
+  }
+
+  public void testGenericAssistedFactory() {
+    final TypeLiteral<GenericColoredCarFactory<Mustang>> mustangTypeLiteral
+        = new TypeLiteral<GenericColoredCarFactory<Mustang>>() {};
+    final TypeLiteral<GenericColoredCarFactory<Camaro>> camaroTypeLiteral
+        = new TypeLiteral<GenericColoredCarFactory<Camaro>>() {};
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
+        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
+        bind(mustangTypeLiteral)
+            .toProvider(FactoryProvider.newFactory(mustangTypeLiteral, TypeLiteral.get(Mustang.class)));
+        bind(camaroTypeLiteral)
+            .toProvider(FactoryProvider.newFactory(camaroTypeLiteral, TypeLiteral.get(Camaro.class)));
+      }
+    });
+
+    GenericColoredCarFactory<Mustang> mustangFactory
+        = injector.getInstance(Key.get(mustangTypeLiteral));
+    GenericColoredCarFactory<Camaro> camaroFactory
+        = injector.getInstance(Key.get(camaroTypeLiteral));
+
+    Mustang blueMustang = mustangFactory.create(Color.BLUE);
+    assertEquals(Color.BLUE, blueMustang.color);
+    assertEquals(5.0d, blueMustang.engineSize);
+
+    Camaro redCamaro = camaroFactory.create(Color.RED);
+    assertEquals(Color.RED, redCamaro.color);
+    assertEquals(1984, redCamaro.modelYear);
+    assertEquals(250, redCamaro.horsePower);
+  }
+
+  @SuppressWarnings("unused")
+  public interface Insurance<T extends Car> {
+  }
+
+  public static class MustangInsurance implements Insurance<Mustang> {
+    private final double premium;
+    private final double limit;
+    @SuppressWarnings("unused") private Mustang car;
+
+    @Inject
+    public MustangInsurance(@Named("lowLimit") double limit, @Assisted Mustang car,
+        @Assisted double premium) {
+      this.premium = premium;
+      this.limit = limit;
+      this.car = car;
+    }
+
+    public void sell() {}
+  }
+
+  public static class CamaroInsurance implements Insurance<Camaro> {
+    private final double premium;
+    private final double limit;
+    @SuppressWarnings("unused") private Camaro car;
+
+    @Inject
+    public CamaroInsurance(@Named("highLimit") double limit, @Assisted Camaro car,
+        @Assisted double premium) {
+      this.premium = premium;
+      this.limit = limit;
+      this.car = car;
+    }
+
+    public void sell() {}
+  }
+
+  public interface MustangInsuranceFactory {
+    public Insurance<Mustang> create(Mustang car, double premium);
+  }
+
+  public interface CamaroInsuranceFactory {
+    public Insurance<Camaro> create(Camaro car, double premium);
+  }
+
+  public void testAssistedFactoryForConcreteType() {
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d);
+        bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d);
+        bind(MustangInsuranceFactory.class).toProvider(
+            FactoryProvider.newFactory(MustangInsuranceFactory.class, MustangInsurance.class));
+        bind(CamaroInsuranceFactory.class).toProvider(
+            FactoryProvider.newFactory(CamaroInsuranceFactory.class, CamaroInsurance.class));
+      }
+    });
+
+    MustangInsuranceFactory mustangInsuranceFactory =
+        injector.getInstance(MustangInsuranceFactory.class);
+    CamaroInsuranceFactory camaroInsuranceFactory =
+        injector.getInstance(CamaroInsuranceFactory.class);
+
+    Mustang mustang = new Mustang(5000d, Color.BLACK);
+    MustangInsurance mustangPolicy =
+        (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d);
+    assertEquals(800.0d, mustangPolicy.premium);
+    assertEquals(50000.0d, mustangPolicy.limit);
+
+    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
+    CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
+    assertEquals(800.0d, camaroPolicy.premium);
+    assertEquals(100000.0d, camaroPolicy.limit);
+  }
+
+  public interface InsuranceFactory<T extends Car> {
+    public Insurance<T> create(T car, double premium);
+  }
+
+  public void testAssistedFactoryForParameterizedType() {
+    final TypeLiteral<InsuranceFactory<Mustang>> mustangInsuranceFactoryType =
+        new TypeLiteral<InsuranceFactory<Mustang>>() {};
+    final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType =
+        new TypeLiteral<InsuranceFactory<Camaro>>() {};
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d);
+        bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d);
+        bind(mustangInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
+            mustangInsuranceFactoryType, TypeLiteral.get(MustangInsurance.class)));
+        bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
+            camaroInsuranceFactoryType, TypeLiteral.get(CamaroInsurance.class)));
+      }
+    });
+
+    InsuranceFactory<Mustang> mustangInsuranceFactory =
+        injector.getInstance(Key.get(mustangInsuranceFactoryType));
+    InsuranceFactory<Camaro> camaroInsuranceFactory =
+        injector.getInstance(Key.get(camaroInsuranceFactoryType));
+
+    Mustang mustang = new Mustang(5000d, Color.BLACK);
+    MustangInsurance mustangPolicy =
+        (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d);
+    assertEquals(800.0d, mustangPolicy.premium);
+    assertEquals(50000.0d, mustangPolicy.limit);
+
+    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
+    CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
+    assertEquals(800.0d, camaroPolicy.premium);
+    assertEquals(100000.0d, camaroPolicy.limit);
+  }
+
+  public static class AutoInsurance<T extends Car> implements Insurance<T> {
+    private final double premium;
+    private final double limit;
+    private final T car;
+
+    @Inject
+    public AutoInsurance(double limit, @Assisted T car, @Assisted double premium) {
+      this.limit = limit;
+      this.car = car;
+      this.premium = premium;
+    }
+
+    public void sell() {}
+  }
+
+  public void testAssistedFactoryForTypeVariableParameters() {
+    final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType =
+        new TypeLiteral<InsuranceFactory<Camaro>>() {};
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(50000.0d);
+        bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
+            camaroInsuranceFactoryType, new TypeLiteral<AutoInsurance<Camaro>>() {}));
+      }
+    });
+
+    InsuranceFactory<Camaro> camaroInsuranceFactory =
+        injector.getInstance(Key.get(camaroInsuranceFactoryType));
+
+    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
+    AutoInsurance<?> camaroPolicy =
+        (AutoInsurance<?>) camaroInsuranceFactory.create(camaro, 800.0d);
+    assertEquals(800.0d, camaroPolicy.premium);
+    assertEquals(50000.0d, camaroPolicy.limit);
+    assertEquals(camaro, camaroPolicy.car);
+  }
+
+  public void testInjectingAndUsingInjector() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Segway.class));
+      }
+    });
+
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+    Segway green = (Segway)carFactory.create(Color.GREEN);
+    assertSame(Color.GREEN, green.getColor());
+    assertSame(Color.GREEN, green.getColor());
+    
+    Segway pink = (Segway)carFactory.create(Color.PINK);
+    assertSame(Color.PINK, pink.getColor());
+    assertSame(Color.PINK, pink.getColor());
+    assertSame(Color.GREEN, green.getColor());
+  }
+  
+  public void testDuplicateAssistedFactoryBinding() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE);
+    assertEquals(Color.BLUE, blueMustang.color);
+    assertEquals(5.0d, blueMustang.engineSize);
+
+    Mustang redMustang = (Mustang) carFactory.create(Color.RED);
+    assertEquals(Color.RED, redMustang.color);
+    assertEquals(5.0d, redMustang.engineSize);
+  }
+
+  public interface Equals {
+
+    enum ComparisonMethod { SHALLOW, DEEP; }
+
+    interface Factory {
+      Equals equals(Equals.ComparisonMethod comparisonMethod);
+    }
+
+    public static class Impl implements Equals {
+      private final double sigma;
+      private final ComparisonMethod comparisonMethod;
+
+      @AssistedInject
+      public Impl(double sigma, @Assisted ComparisonMethod comparisonMethod) {
+        this.sigma = sigma;
+        this.comparisonMethod = comparisonMethod;
+      }
+    }
+  }
+
+  public void testFactoryMethodCalledEquals() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(0.01d);
+        bind(Equals.Factory.class).toProvider(
+            FactoryProvider.newFactory(Equals.Factory.class, Equals.Impl.class));
+      }
+    });
+    Equals.Factory equalsFactory = injector.getInstance(Equals.Factory.class);
+    Equals.Impl shallowEquals = (Impl) equalsFactory.equals(ComparisonMethod.SHALLOW);
+    assertEquals(ComparisonMethod.SHALLOW, shallowEquals.comparisonMethod);
+    assertEquals(0.01d, shallowEquals.sigma);
+  }
+
+  static class Segway implements Car {
+    @Inject Injector injector;
+
+    Color getColor() { return injector.getInstance(Key.get(Color.class, FactoryProvider2.DEFAULT_ANNOTATION)); }
+  }
+
+  public void testReturnValueMatchesParamValue() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      public void configure() {
+        install(new FactoryModuleBuilder().build(Delegater.Factory.class));
+      }
+    });
+    Delegater delegate = new Delegater();
+    Delegater user = injector.getInstance(Delegater.Factory.class).create(delegate);
+    assertSame(delegate, user.delegate);
+  }
+
+  static class Delegater {
+    interface Factory {
+      Delegater create(Delegater delegate);
+    }
+
+    private final Delegater delegate;
+
+    @Inject Delegater(@Assisted Delegater delegater) {
+      this.delegate = delegater;
+    }
+
+    Delegater() {
+      this.delegate = null;
+    }
+  }
+
+  public static abstract class AbstractAssisted {
+    interface Factory<O extends AbstractAssisted, I extends CharSequence> {
+      O create(I string);
+    }
+  }
+
+  static class ConcreteAssisted extends AbstractAssisted {
+    @Inject ConcreteAssisted(@SuppressWarnings("unused") @Assisted String string) {}
+  }
+
+  static class ConcreteAssistedWithOverride extends AbstractAssisted {
+    @AssistedInject
+    ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted String string) {}
+
+    @AssistedInject
+    ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted StringBuilder sb) {}
+
+    interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> {
+      @Override ConcreteAssistedWithOverride create(String string);
+    }
+
+    interface Factory2 extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> {
+      @Override ConcreteAssistedWithOverride create(String string);
+      ConcreteAssistedWithOverride create(StringBuilder sb);
+    }
+  }
+
+  static class ConcreteAssistedWithoutOverride extends AbstractAssisted {
+    @Inject ConcreteAssistedWithoutOverride(@SuppressWarnings("unused") @Assisted String string) {}
+    interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> {}
+  }
+
+  public static class Public extends AbstractAssisted {
+    @AssistedInject Public(@SuppressWarnings("unused") @Assisted String string) {}
+    @AssistedInject Public(@SuppressWarnings("unused") @Assisted StringBuilder sb) {}
+
+    public interface Factory extends AbstractAssisted.Factory<Public, String> {
+      @Override Public create(String string);
+      Public create(StringBuilder sb);
+    }
+  }
+
+  // See https://github.com/google/guice/issues/904
+  public void testGeneratedDefaultMethodsForwardCorrectly() {
+    final Key<AbstractAssisted.Factory<ConcreteAssisted, String>> concreteKey =
+        new Key<AbstractAssisted.Factory<ConcreteAssisted, String>>() {};
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        install(new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory.class));
+        install(new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory2.class));
+        install(new FactoryModuleBuilder().build(ConcreteAssistedWithoutOverride.Factory.class));
+        install(new FactoryModuleBuilder().build(Public.Factory.class));
+        install(new FactoryModuleBuilder().build(concreteKey));
+      }
+    });
+
+    ConcreteAssistedWithOverride.Factory factory1 =
+        injector.getInstance(ConcreteAssistedWithOverride.Factory.class);
+    factory1.create("foo");
+    AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory1Abstract = factory1;
+    factory1Abstract.create("foo");
+
+    ConcreteAssistedWithOverride.Factory2 factory2 =
+        injector.getInstance(ConcreteAssistedWithOverride.Factory2.class);
+    factory2.create("foo");
+    factory2.create(new StringBuilder("foo"));
+    AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory2Abstract = factory2;
+    factory2Abstract.create("foo");
+
+    ConcreteAssistedWithoutOverride.Factory factory3 =
+        injector.getInstance(ConcreteAssistedWithoutOverride.Factory.class);
+    factory3.create("foo");
+    AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> factory3Abstract = factory3;
+    factory3Abstract.create("foo");
+
+    Public.Factory factory4 = injector.getInstance(Public.Factory.class);
+    factory4.create("foo");
+    factory4.create(new StringBuilder("foo"));
+    AbstractAssisted.Factory<Public, String> factory4Abstract = factory4;
+    factory4Abstract.create("foo");
+
+    AbstractAssisted.Factory<ConcreteAssisted, String> factory5 =
+        injector.getInstance(concreteKey);
+    factory5.create("foo");
+  }
+}
diff --git a/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProviderTest.java b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProviderTest.java
new file mode 100644
index 0000000..c8f4b12
--- /dev/null
+++ b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProviderTest.java
@@ -0,0 +1,840 @@
+/**
+ * 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 com.google.inject.assistedinject;
+
+import static com.google.inject.Asserts.assertContains;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.ConfigurationException;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.assistedinject.FactoryProviderTest.Equals.ComparisonMethod;
+import com.google.inject.assistedinject.FactoryProviderTest.Equals.Impl;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+
+import junit.framework.TestCase;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+@SuppressWarnings("deprecation")
+public class FactoryProviderTest extends TestCase {
+  
+  private enum Color { BLUE, GREEN, RED, GRAY, BLACK, ORANGE, PINK }
+
+  public void testAssistedFactory() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE);
+    assertEquals(Color.BLUE, blueMustang.color);
+    assertEquals(5.0d, blueMustang.engineSize);
+
+    Mustang redMustang = (Mustang) carFactory.create(Color.RED);
+    assertEquals(Color.RED, redMustang.color);
+    assertEquals(5.0d, redMustang.engineSize);
+  }
+
+  public void testFactoryBindingDependencies() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+      }
+    });
+
+    Binding<?> binding = injector.getBinding(ColoredCarFactory.class);
+    HasDependencies hasDependencies = (HasDependencies) binding;
+    assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(double.class))),
+        hasDependencies.getDependencies());
+  }
+
+  public void testAssistedFactoryWithAnnotations() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
+        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Camaro.class));
+      }
+    });
+
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Camaro blueCamaro = (Camaro) carFactory.create(Color.BLUE);
+    assertEquals(Color.BLUE, blueCamaro.color);
+    assertEquals(1984, blueCamaro.modelYear);
+    assertEquals(250, blueCamaro.horsePower);
+
+    Camaro redCamaro = (Camaro) carFactory.create(Color.RED);
+    assertEquals(Color.RED, redCamaro.color);
+    assertEquals(1984, redCamaro.modelYear);
+    assertEquals(250, redCamaro.horsePower);
+  }
+
+  interface Car {
+  }
+
+  interface ColoredCarFactory {
+    Car create(Color color);
+  }
+
+  public static class Mustang implements Car {
+    private final double engineSize;
+    private final Color color;
+
+    @AssistedInject
+    public Mustang(double engineSize, @Assisted Color color) {
+      this.engineSize = engineSize;
+      this.color = color;
+    }
+  }
+
+  public static class Camaro implements Car {
+    private final int horsePower;
+    private final int modelYear;
+    private final Color color;
+
+    @AssistedInject
+    public Camaro(
+        @Named("horsePower")int horsePower,
+        @Named("modelYear")int modelYear,
+        @Assisted Color color) {
+      this.horsePower = horsePower;
+      this.modelYear = modelYear;
+      this.color = color;
+    }
+  }
+
+  interface SummerCarFactory {
+    Car create(Color color, boolean convertable);
+    Car createConvertible(Color color);
+  }
+
+  public void testFactoryWithMultipleMethods() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(float.class).toInstance(140f);
+        bind(SummerCarFactory.class).toProvider(
+            FactoryProvider.newFactory(SummerCarFactory.class, Corvette.class));
+      }
+    });
+
+    SummerCarFactory carFactory = injector.getInstance(SummerCarFactory.class);
+
+    Corvette blueCorvette = (Corvette) carFactory.createConvertible(Color.BLUE);
+    assertEquals(Color.BLUE, blueCorvette.color);
+    assertEquals(100f, blueCorvette.maxMph);
+    assertTrue(blueCorvette.isConvertable);
+
+    Corvette redCorvette = (Corvette) carFactory.create(Color.RED, false);
+    assertEquals(Color.RED, redCorvette.color);
+    assertEquals(140f, redCorvette.maxMph);
+    assertFalse(redCorvette.isConvertable);
+  }
+
+  public static class Corvette implements Car {
+    private boolean isConvertable;
+    private Color color;
+    private float maxMph;
+
+    @AssistedInject
+    public Corvette(@Assisted Color color) {
+      this(color, 100f, true);
+    }
+
+    @SuppressWarnings("unused")
+    public Corvette(@Assisted Color color, @Assisted boolean isConvertable) {
+      throw new IllegalStateException("Not an @AssistedInject constructor");
+    }
+
+    @AssistedInject
+    public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertable) {
+      this.isConvertable = isConvertable;
+      this.color = color;
+      this.maxMph = maxMph;
+    }
+  }
+
+  public void testFactoryMethodsMismatch() {
+    try {
+      FactoryProvider.newFactory(SummerCarFactory.class, Beetle.class);
+      fail();
+    } catch(ConfigurationException e) {
+      assertContains(e.getMessage(), "Constructor mismatch");
+    }
+  }
+
+  public static class Beetle implements Car {
+    @AssistedInject
+    @SuppressWarnings("unused")
+    public Beetle(@Assisted Color color) {
+      throw new IllegalStateException("Conflicting constructors");
+    }
+    @AssistedInject
+    @SuppressWarnings("unused")
+    public Beetle(@Assisted Color color, @Assisted boolean isConvertable) {
+      throw new IllegalStateException("Conflicting constructors");
+    }
+    @AssistedInject
+    @SuppressWarnings("unused")
+    public Beetle(@Assisted Color color, @Assisted boolean isConvertable, float maxMph) {
+      throw new IllegalStateException("Conflicting constructors");
+    }
+  }
+
+  public void testMethodsAndFieldsGetInjected() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("turbo");
+        bind(int.class).toInstance(911);
+        bind(double.class).toInstance(50000d);
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Porshe.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Porshe grayPorshe = (Porshe) carFactory.create(Color.GRAY);
+    assertEquals(Color.GRAY, grayPorshe.color);
+    assertEquals(50000d, grayPorshe.price);
+    assertEquals(911, grayPorshe.model);
+    assertEquals("turbo", grayPorshe.name);
+  }
+
+  public static class Porshe implements Car {
+    private final Color color;
+    private final double price;
+    private @Inject String name;
+    private int model;
+
+    @AssistedInject
+    public Porshe(@Assisted Color color, double price) {
+      this.color = color;
+      this.price = price;
+    }
+
+    @Inject void setModel(int model) {
+      this.model = model;
+    }
+  }
+
+  public void testProviderInjection() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("trans am");
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Firebird.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Firebird blackFirebird = (Firebird) carFactory.create(Color.BLACK);
+    assertEquals(Color.BLACK, blackFirebird.color);
+    assertEquals("trans am", blackFirebird.modifiersProvider.get());
+  }
+
+  public static class Firebird implements Car {
+    private final Provider<String> modifiersProvider;
+    private final Color color;
+
+    @AssistedInject
+    public Firebird(Provider<String> modifiersProvider, @Assisted Color color) {
+      this.modifiersProvider = modifiersProvider;
+      this.color = color;
+    }
+  }
+
+  public void testTypeTokenInjection() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(new TypeLiteral<Set<String>>() {}).toInstance(Collections.singleton("Flux Capacitor"));
+        bind(new TypeLiteral<Set<Integer>>() {}).toInstance(Collections.singleton(88));
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, DeLorean.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    DeLorean deLorean = (DeLorean) carFactory.create(Color.GRAY);
+    assertEquals(Color.GRAY, deLorean.color);
+    assertEquals("Flux Capacitor", deLorean.features.iterator().next());
+    assertEquals(new Integer(88), deLorean.featureActivationSpeeds.iterator().next());
+  }
+
+  public static class DeLorean implements Car {
+    private final Set<String> features;
+    private final Set<Integer> featureActivationSpeeds;
+    private final Color color;
+
+    @AssistedInject
+    public DeLorean(
+        Set<String> extraFeatures, Set<Integer> featureActivationSpeeds, @Assisted Color color) {
+      this.features = extraFeatures;
+      this.featureActivationSpeeds = featureActivationSpeeds;
+      this.color = color;
+    }
+  }
+
+  public void testTypeTokenProviderInjection() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(new TypeLiteral<Set<String>>() { }).toInstance(Collections.singleton("Datsun"));
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Z.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Z orangeZ = (Z) carFactory.create(Color.ORANGE);
+    assertEquals(Color.ORANGE, orangeZ.color);
+    assertEquals("Datsun", orangeZ.manufacturersProvider.get().iterator().next());
+  }
+
+  public static class Z implements Car {
+    private final Provider<Set<String>> manufacturersProvider;
+    private final Color color;
+
+    @AssistedInject
+    public Z(Provider<Set<String>> manufacturersProvider, @Assisted Color color) {
+      this.manufacturersProvider = manufacturersProvider;
+      this.color = color;
+    }
+  }
+  
+  public static class Prius implements Car {
+    @SuppressWarnings("unused")
+    private final Color color;
+    
+    @AssistedInject
+    private Prius(@Assisted Color color) {
+      this.color = color;
+    }
+  }
+  
+  public void testAssistInjectionInNonPublicConstructor() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Prius.class));
+      }
+    });
+    injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE);
+  }
+
+  public static class ExplodingCar implements Car {
+    @AssistedInject
+    public ExplodingCar(@SuppressWarnings("unused") @Assisted Color color) {
+      throw new IllegalStateException("kaboom!");
+    }
+  }
+
+  public void testExceptionDuringConstruction() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(ColoredCarFactory.class, ExplodingCar.class));
+      }
+    });
+    try {
+      injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE);
+      fail();
+    } catch (IllegalStateException e) {
+      assertEquals("kaboom!", e.getMessage());
+    }
+  }
+  
+  public static class DefectiveCar implements Car {
+    @AssistedInject
+    public DefectiveCar() throws ExplosionException {
+      throw new ExplosionException();
+    }
+  }
+  
+  public static class ExplosionException extends Exception { }
+  public static class FireException extends Exception { }
+  
+  public interface DefectiveCarFactoryWithNoExceptions {
+    Car createCar();
+  }
+
+  public interface DefectiveCarFactory {
+    Car createCar() throws FireException;
+  }
+
+  public void testFactoryMethodMustDeclareAllConstructorExceptions() {
+    try {
+      FactoryProvider.newFactory(DefectiveCarFactoryWithNoExceptions.class, DefectiveCar.class);
+      fail();
+    } catch (ConfigurationException expected) {
+      assertContains(expected.getMessage(), "no compatible exception is thrown");
+    }
+  }
+
+  public interface CorrectDefectiveCarFactory {
+    Car createCar() throws FireException, ExplosionException;
+  }
+  
+  public void testConstructorExceptionsAreThrownByFactory() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(CorrectDefectiveCarFactory.class).toProvider(
+            FactoryProvider.newFactory(
+                CorrectDefectiveCarFactory.class, DefectiveCar.class));
+      }
+    });
+    try {
+      injector.getInstance(CorrectDefectiveCarFactory.class).createCar();
+      fail();
+    } catch (FireException e) {
+      fail();
+    } catch (ExplosionException expected) {
+    }
+  }
+
+  public static class MultipleConstructorDefectiveCar implements Car {
+    @AssistedInject
+    public MultipleConstructorDefectiveCar() throws ExplosionException {
+      throw new ExplosionException();
+    }
+
+    @AssistedInject
+    public MultipleConstructorDefectiveCar(@SuppressWarnings("unused") @Assisted Color c)
+        throws FireException {
+      throw new FireException();
+    }
+  }
+
+  public interface MultipleConstructorDefectiveCarFactory {
+    Car createCar() throws ExplosionException;
+    Car createCar(Color r) throws FireException;
+  }
+
+  public void testMultipleConstructorExceptionMatching() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(MultipleConstructorDefectiveCarFactory.class).toProvider(
+            FactoryProvider.newFactory(
+                MultipleConstructorDefectiveCarFactory.class,
+                MultipleConstructorDefectiveCar.class));
+      }
+    });
+    MultipleConstructorDefectiveCarFactory factory
+        = injector.getInstance(MultipleConstructorDefectiveCarFactory.class);
+    try {
+      factory.createCar();
+      fail();
+    } catch (ExplosionException expected) {
+    }
+
+    try {
+      factory.createCar(Color.RED);
+      fail();
+    } catch (FireException expected) {
+    }
+  }
+  
+  public static class WildcardCollection {
+    
+    public interface Factory {
+      WildcardCollection create(Collection<?> items);
+    }
+
+    @AssistedInject
+    public WildcardCollection(@SuppressWarnings("unused") @Assisted Collection<?> items) { }
+  }
+  
+  public void testWildcardGenerics() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(WildcardCollection.Factory.class).toProvider(
+            FactoryProvider.newFactory(
+                WildcardCollection.Factory.class,
+                WildcardCollection.class));
+      }
+    });
+    WildcardCollection.Factory factory = injector.getInstance(WildcardCollection.Factory.class);
+    factory.create(Collections.emptyList());
+  }
+  
+  public static class SteeringWheel {}
+  
+  public static class Fiat implements Car {
+    @SuppressWarnings("unused")
+    private final SteeringWheel steeringWheel;
+    @SuppressWarnings("unused")
+    private final Color color;
+    
+    @AssistedInject
+    public Fiat(SteeringWheel steeringWheel, @Assisted Color color) {
+      this.steeringWheel = steeringWheel;
+      this.color = color;
+    }
+  }
+  
+  public void testFactoryWithImplicitBindings() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(ColoredCarFactory.class).toProvider(
+            FactoryProvider.newFactory(
+                ColoredCarFactory.class, 
+                Fiat.class));
+      }
+    });
+
+    ColoredCarFactory coloredCarFactory = injector.getInstance(ColoredCarFactory.class);
+    Fiat fiat = (Fiat) coloredCarFactory.create(Color.GREEN);
+    assertEquals(Color.GREEN, fiat.color);
+    assertNotNull(fiat.steeringWheel);
+  }
+  
+  public void testFactoryFailsWithMissingBinding() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(ColoredCarFactory.class)
+              .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) Parameter of type 'double' is not injectable or annotated with @Assisted");
+    }
+  }
+  
+  public void testMethodsDeclaredInObject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(Double.class).toInstance(5.0d);
+          bind(ColoredCarFactory.class)
+              .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+        }
+      });
+    
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+    
+    carFactory.equals(carFactory);
+    carFactory.hashCode();
+    carFactory.toString();
+  }
+
+  public void testAssistedInjectConstructorAndAssistedFactoryParameterMustNotMix() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(Double.class).toInstance(5.0d);
+          bind(AssistedParamsFactory.class)
+              .toProvider(FactoryProvider.newFactory(AssistedParamsFactory.class, Mustang.class));
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "Factory method "
+          + AssistedParamsFactory.class.getName() + ".create() has an @Assisted parameter, which "
+          + "is incompatible with the deprecated @AssistedInject annotation.");
+    }
+  }
+
+  interface AssistedParamsFactory {
+    Car create(@Assisted Color color);
+  }
+
+  interface GenericColoredCarFactory<T extends Car> {
+    T create(Color color);
+  }
+
+  public void testGenericAssistedFactory() {
+    final TypeLiteral<GenericColoredCarFactory<Mustang>> mustangTypeLiteral
+        = new TypeLiteral<GenericColoredCarFactory<Mustang>>() {};
+    final TypeLiteral<GenericColoredCarFactory<Camaro>> camaroTypeLiteral
+        = new TypeLiteral<GenericColoredCarFactory<Camaro>>() {};
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
+        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
+        bind(mustangTypeLiteral).toProvider(
+            FactoryProvider.newFactory(mustangTypeLiteral, TypeLiteral.get(Mustang.class)));
+        bind(camaroTypeLiteral).toProvider(
+            FactoryProvider.newFactory(camaroTypeLiteral, TypeLiteral.get(Camaro.class)));
+      }
+    });
+
+    GenericColoredCarFactory<Mustang> mustangFactory
+        = injector.getInstance(Key.get(mustangTypeLiteral));
+    GenericColoredCarFactory<Camaro> camaroFactory
+        = injector.getInstance(Key.get(camaroTypeLiteral));
+
+    Mustang blueMustang = mustangFactory.create(Color.BLUE);
+    assertEquals(Color.BLUE, blueMustang.color);
+    assertEquals(5.0d, blueMustang.engineSize);
+
+    Camaro redCamaro = camaroFactory.create(Color.RED);
+    assertEquals(Color.RED, redCamaro.color);
+    assertEquals(1984, redCamaro.modelYear);
+    assertEquals(250, redCamaro.horsePower);
+  }
+
+  @SuppressWarnings("unused")
+  public interface Insurance<T extends Car> {
+  }
+
+  public static class MustangInsurance implements Insurance<Mustang> {
+    private final double premium;
+    private final double limit;
+    @SuppressWarnings("unused") private Mustang car;
+
+    @AssistedInject
+    public MustangInsurance(@Named("lowLimit") double limit, @Assisted Mustang car,
+        @Assisted double premium) {
+      this.premium = premium;
+      this.limit = limit;
+      this.car = car;
+    }
+
+    public void sell() {}
+  }
+
+  public static class CamaroInsurance implements Insurance<Camaro> {
+    private final double premium;
+    private final double limit;
+    @SuppressWarnings("unused") private Camaro car;
+
+    @AssistedInject
+    public CamaroInsurance(@Named("highLimit") double limit, @Assisted Camaro car,
+        @Assisted double premium) {
+      this.premium = premium;
+      this.limit = limit;
+      this.car = car;
+    }
+
+    public void sell() {}
+  }
+
+  public interface MustangInsuranceFactory {
+    public Insurance<Mustang> create(Mustang car, double premium);
+  }
+
+  public interface CamaroInsuranceFactory {
+    public Insurance<Camaro> create(Camaro car, double premium);
+  }
+
+  public void testAssistedFactoryForConcreteType() {
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d);
+        bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d);
+        bind(MustangInsuranceFactory.class).toProvider(
+            FactoryProvider.newFactory(MustangInsuranceFactory.class, MustangInsurance.class));
+        bind(CamaroInsuranceFactory.class).toProvider(
+            FactoryProvider.newFactory(CamaroInsuranceFactory.class, CamaroInsurance.class));
+      }
+    });
+
+    MustangInsuranceFactory mustangInsuranceFactory =
+        injector.getInstance(MustangInsuranceFactory.class);
+    CamaroInsuranceFactory camaroInsuranceFactory =
+        injector.getInstance(CamaroInsuranceFactory.class);
+
+    Mustang mustang = new Mustang(5000d, Color.BLACK);
+    MustangInsurance mustangPolicy =
+        (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d);
+    assertEquals(800.0d, mustangPolicy.premium);
+    assertEquals(50000.0d, mustangPolicy.limit);
+
+    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
+    CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
+    assertEquals(800.0d, camaroPolicy.premium);
+    assertEquals(100000.0d, camaroPolicy.limit);
+  }
+
+  public interface InsuranceFactory<T extends Car> {
+    public Insurance<T> create(T car, double premium);
+  }
+
+  public void testAssistedFactoryForParameterizedType() {
+    final TypeLiteral<InsuranceFactory<Mustang>> mustangInsuranceFactoryType =
+        new TypeLiteral<InsuranceFactory<Mustang>>() {};
+    final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType =
+        new TypeLiteral<InsuranceFactory<Camaro>>() {};
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d);
+        bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d);
+        bind(mustangInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
+            mustangInsuranceFactoryType, TypeLiteral.get(MustangInsurance.class)));
+        bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
+            camaroInsuranceFactoryType, TypeLiteral.get(CamaroInsurance.class)));
+      }
+    });
+
+    InsuranceFactory<Mustang> mustangInsuranceFactory =
+        injector.getInstance(Key.get(mustangInsuranceFactoryType));
+    InsuranceFactory<Camaro> camaroInsuranceFactory =
+        injector.getInstance(Key.get(camaroInsuranceFactoryType));
+
+    Mustang mustang = new Mustang(5000d, Color.BLACK);
+    MustangInsurance mustangPolicy =
+        (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d);
+    assertEquals(800.0d, mustangPolicy.premium);
+    assertEquals(50000.0d, mustangPolicy.limit);
+
+    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
+    CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
+    assertEquals(800.0d, camaroPolicy.premium);
+    assertEquals(100000.0d, camaroPolicy.limit);
+  }
+
+  public static class AutoInsurance<T extends Car> implements Insurance<T> {
+    private final double premium;
+    private final double limit;
+    private final T car;
+
+    @AssistedInject
+    public AutoInsurance(double limit, @Assisted T car, @Assisted double premium) {
+      this.limit = limit;
+      this.car = car;
+      this.premium = premium;
+    }
+
+    public void sell() {}
+  }
+
+  public void testAssistedFactoryForTypeVariableParameters() {
+    final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType =
+        new TypeLiteral<InsuranceFactory<Camaro>>() {};
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(50000.0d);
+        bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
+            camaroInsuranceFactoryType, new TypeLiteral<AutoInsurance<Camaro>>() {}));
+      }
+    });
+
+    InsuranceFactory<Camaro> camaroInsuranceFactory =
+        injector.getInstance(Key.get(camaroInsuranceFactoryType));
+
+    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
+    AutoInsurance<?> camaroPolicy =
+        (AutoInsurance<?>) camaroInsuranceFactory.create(camaro, 800.0d);
+    assertEquals(800.0d, camaroPolicy.premium);
+    assertEquals(50000.0d, camaroPolicy.limit);
+    assertEquals(camaro, camaroPolicy.car);
+  }
+
+  public void testDuplicateAssistedFactoryBinding() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(5.0d);
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+        bind(ColoredCarFactory.class)
+            .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
+      }
+    });
+    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
+
+    Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE);
+    assertEquals(Color.BLUE, blueMustang.color);
+    assertEquals(5.0d, blueMustang.engineSize);
+
+    Mustang redMustang = (Mustang) carFactory.create(Color.RED);
+    assertEquals(Color.RED, redMustang.color);
+    assertEquals(5.0d, redMustang.engineSize);
+  }
+
+  public interface Equals {
+
+    enum ComparisonMethod { SHALLOW, DEEP; }
+
+    interface Factory {
+      Equals equals(Equals.ComparisonMethod comparisonMethod);
+    }
+
+    public static class Impl implements Equals {
+      private final double sigma;
+      private final ComparisonMethod comparisonMethod;
+
+      @Inject
+      public Impl(double sigma, @Assisted ComparisonMethod comparisonMethod) {
+        this.sigma = sigma;
+        this.comparisonMethod = comparisonMethod;
+      }
+    }
+  }
+
+  public void testFactoryMethodCalledEquals() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Double.class).toInstance(0.01d);
+        bind(Equals.Factory.class).toProvider(
+            FactoryProvider.newFactory(Equals.Factory.class, Equals.Impl.class));
+      }
+    });
+    Equals.Factory equalsFactory = injector.getInstance(Equals.Factory.class);
+    Equals.Impl shallowEquals = (Impl) equalsFactory.equals(ComparisonMethod.SHALLOW);
+    assertEquals(ComparisonMethod.SHALLOW, shallowEquals.comparisonMethod);
+    assertEquals(0.01d, shallowEquals.sigma);
+  }
+}
\ No newline at end of file
diff --git a/extensions/assistedinject/test/com/google/inject/assistedinject/ManyConstructorsTest.java b/extensions/assistedinject/test/com/google/inject/assistedinject/ManyConstructorsTest.java
new file mode 100644
index 0000000..f360f06
--- /dev/null
+++ b/extensions/assistedinject/test/com/google/inject/assistedinject/ManyConstructorsTest.java
@@ -0,0 +1,277 @@
+/**
+ * Copyright (C) 2010 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.inject.assistedinject;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Asserts;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import junit.framework.TestCase;
+
+/**
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class ManyConstructorsTest extends TestCase {
+  
+  public void testTwoConstructors() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder().build(Factory.class));
+      }
+    });
+    Factory factory = injector.getInstance(Factory.class);
+    Foo noIndex = factory.create("no index");
+    assertEquals("no index", noIndex.name);
+    assertNull(noIndex.index);
+    Foo index = factory.create("index", 1);
+    assertEquals("index", index.name);
+    assertEquals(1, index.index.intValue());
+  }
+  
+  public void testDifferentOrderParameters() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder().build(OtherFactory.class));
+      }
+    });
+    OtherFactory factory = injector.getInstance(OtherFactory.class);
+    Foo noIndex = factory.create("no index");
+    assertEquals("no index", noIndex.name);
+    assertNull(noIndex.index);
+    Foo index = factory.create(1, "index");
+    assertEquals("index", index.name);
+    assertEquals(1, index.index.intValue());
+    Foo index2 = factory.create("index", 2);
+    assertEquals("index", index2.name);
+    assertEquals(2, index2.index.intValue());
+  }
+  
+  public void testInterfaceToImpl() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder()
+          .implement(Bar.class, Foo.class)
+          .build(BarFactory.class));
+      }
+    });
+    BarFactory factory = injector.getInstance(BarFactory.class);
+    Bar noIndex = factory.create("no index");
+    assertEquals("no index", noIndex.getName());
+    assertNull(noIndex.getIndex());
+    Bar index = factory.create("index", 1);
+    assertEquals("index", index.getName());
+    assertEquals(1, index.getIndex().intValue());
+  }
+  
+  public void testUsingOneConstructor() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder().build(SimpleFactory.class));
+      }
+    });
+    SimpleFactory factory = injector.getInstance(SimpleFactory.class);
+    Foo noIndex = factory.create("no index");
+    assertEquals("no index", noIndex.name);
+    assertNull(noIndex.index);
+    
+    injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder().build(SimpleFactory2.class));
+      }
+    });
+    SimpleFactory2 factory2 = injector.getInstance(SimpleFactory2.class);
+    Foo index = factory2.create("index", 1);
+    assertEquals("index", index.name);
+    assertEquals(1, index.index.intValue());
+  }
+  
+  public void testTooManyMatchingConstructors() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new FactoryModuleBuilder()
+            .implement(Foo.class, TooManyMatches.class)
+            .build(SimpleFactory2.class));
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      Asserts.assertContains(expected.getMessage(), "1) " + TooManyMatches.class.getName()
+          + " has more than one constructor annotated with @AssistedInject that "
+          + "matches the parameters in method " + SimpleFactory2.class.getName());
+    }
+  }
+
+  public void testNoMatchingConstructorsBecauseTooManyParams() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new FactoryModuleBuilder().build(ComplexFactory.class));
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      Asserts.assertContains(expected.getMessage(), "1) " + Foo.class.getName()
+          + " has @AssistedInject constructors, but none of them match the parameters in method "
+          + ComplexFactory.class.getName());
+    }
+  }
+  
+  public void testNoMatchingConstrucotsBecauseTooLittleParams() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(new FactoryModuleBuilder().build(NullFactory.class));
+        }
+      });
+      fail("should have failed");
+    } catch (CreationException expected) {
+      Asserts.assertContains(expected.getMessage(), "1) " + Foo.class.getName()
+          + " has @AssistedInject constructors, but none of them match the parameters in method "
+          + NullFactory.class.getName());
+    }
+  }
+
+  public static interface ComplexFactory {
+    Foo create(String name, int idx, float weight);
+  }
+  
+  public static interface NullFactory {
+    Foo create();
+  }
+  
+  public static interface OtherFactory {
+    Foo create(String name, int idx);
+    Foo create(int idx, String name);
+    Foo create(String name);
+  }
+
+  
+  public static interface Factory {
+    Foo create(String name);
+    Foo create(String name, int idx);
+  }
+  
+  public static interface BarFactory {
+    Bar create(String name);
+    Bar create(String name, int idx);
+  }
+  
+  public static interface SimpleFactory {
+    Foo create(String name);
+  }
+  
+  public static interface SimpleFactory2 {
+    Foo create(String name, int idx);
+  }
+  
+  public static class TooManyMatches extends Foo {
+    @AssistedInject TooManyMatches(@Assisted String name, @Assisted int index) {
+    }
+    
+    @AssistedInject TooManyMatches(@Assisted int index, @Assisted String name) {
+    }    
+  }
+  
+  public static class Foo implements Bar {
+    private String name;
+    private Integer index;
+    
+    Foo() {}
+    
+    @AssistedInject Foo(@Assisted String name) {
+      this.name = name;
+      this.index = null;
+    }
+    
+    @AssistedInject Foo(@Assisted String name, @Assisted int index) {
+      this.name = name;
+      this.index = index;
+    }
+    
+    Foo(String a, String b, String c) {
+      
+    }
+    
+    public String getName() { return name; }
+    public Integer getIndex() { return index; }
+  }
+  
+  public static interface Bar {
+    String getName();
+    Integer getIndex();
+  }
+  
+  public void testDependenciesAndOtherAnnotations() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new FactoryModuleBuilder().build(FamilyFarmFactory.class));
+      }
+    });
+    
+    FamilyFarmFactory factory = injector.getInstance(FamilyFarmFactory.class);
+    Farm pops = factory.popsFarm("Pop");
+    assertEquals("Pop", pops.pop);
+    assertEquals(null, pops.mom);
+    Farm moms = factory.momsFarm("Mom");
+    assertEquals(null, moms.pop);
+    assertEquals("Mom", moms.mom);
+    Farm momAndPop = factory.momAndPopsFarm("Mom", "Pop");
+    assertEquals("Pop", momAndPop.pop);
+    assertEquals("Mom", momAndPop.mom);
+  }
+  
+
+  public static interface FamilyFarmFactory {
+    Farm popsFarm(String pop);
+    Farm momsFarm(@Assisted("mom") String mom);
+    Farm momAndPopsFarm(@Assisted("mom") String mom, @Assisted("pop") String pop);
+  }
+  
+  public static class Farm {
+    String pop;
+    String mom;
+    
+    @AssistedInject Farm(@Assisted String pop, Dog dog) {
+      this.pop = pop;
+    }
+    
+    @AssistedInject Farm(@Assisted("mom") String mom, @Assisted("pop") String pop, Cow cow, Dog dog) {
+      this.pop = pop;
+      this.mom = mom;
+    }
+    
+    @AssistedInject Farm(@Assisted("mom") String mom, Cow cow) {
+      this.mom = mom;
+    }
+  }
+  
+  public static class Cow {}
+  public static class Dog {}
+  
+}
diff --git a/extensions/dagger-adapter/build.properties b/extensions/dagger-adapter/build.properties
new file mode 100644
index 0000000..97e53c2
--- /dev/null
+++ b/extensions/dagger-adapter/build.properties
@@ -0,0 +1,8 @@
+lib.dir=../../lib
+ext.lib.dir=lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.daggeradapter.DaggerAdapterTest
+module=com.google.inject.daggeradapter
+fragment=true
diff --git a/extensions/dagger-adapter/build.xml b/extensions/dagger-adapter/build.xml
new file mode 100644
index 0000000..27eb429
--- /dev/null
+++ b/extensions/dagger-adapter/build.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+
+<project name="guice-dagger-adapter" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${ext.lib.dir}" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+    <fileset dir="../multibindings/build" includes="*.jar"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/dagger-adapter/lib/dagger-2.0.jar b/extensions/dagger-adapter/lib/dagger-2.0.jar
new file mode 100644
index 0000000..a7257df
--- /dev/null
+++ b/extensions/dagger-adapter/lib/dagger-2.0.jar
Binary files differ
diff --git a/extensions/dagger-adapter/pom.xml b/extensions/dagger-adapter/pom.xml
new file mode 100644
index 0000000..38692f4
--- /dev/null
+++ b/extensions/dagger-adapter/pom.xml
@@ -0,0 +1,24 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+  <artifactId>guice-dagger-adapter</artifactId>
+  <name>Google Guice - Extensions - Dagger Adapter</name>
+  <dependencies>
+    <dependency>
+      <groupId>com.google.inject.extensions</groupId>
+      <artifactId>guice-multibindings</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.dagger</groupId>
+      <artifactId>dagger</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/extensions/dagger-adapter/src/com/google/inject/daggeradapter/DaggerAdapter.java b/extensions/dagger-adapter/src/com/google/inject/daggeradapter/DaggerAdapter.java
new file mode 100644
index 0000000..eb7aac5
--- /dev/null
+++ b/extensions/dagger-adapter/src/com/google/inject/daggeradapter/DaggerAdapter.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2015 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.inject.daggeradapter;
+
+import com.google.common.base.Objects;
+import com.google.inject.Binder;
+import com.google.inject.Module;
+import com.google.inject.internal.ProviderMethodsModule;
+import com.google.inject.spi.ModuleAnnotatedMethodScanner;
+
+import java.util.Arrays;
+
+/**
+ * A utility to adapt classes annotated with {@link @dagger.Module} such that their
+ * {@link @dagger.Provides} methods can be properly invoked by Guice to perform their
+ * provision operations.
+ *
+ * <p>Simple example: <pre>{@code
+ *   Guice.createInjector(...other modules..., DaggerAdapter.from(new SomeDaggerAdapter()));
+ * }</pre>
+ *
+ * <p>Some notes on usage and compatibility.
+ *   <ul>
+ *     <li>Dagger provider methods have a "SET_VALUES" provision mode not supported by Guice.
+ *     <li>MapBindings are not yet implemented (pending).
+ *     <li>Be careful about stateful modules. In contrast to Dagger (where components are
+ *         expected to be recreated on-demand with new Module instances), Guice typically
+ *         has a single injector with a long lifetime, so your module instance will be used
+ *         throughout the lifetime of the entire app.
+ *     <li>Dagger 1.x uses {@link @Singleton} for all scopes, including shorter-lived scopes
+ *         like per-request or per-activity.  Using modules written with Dagger 1.x usage
+ *         in mind may result in mis-scoped objects.
+ *     <li>Dagger 2.x supports custom scope annotations, but for use in Guice, a custom scope
+ *         implementation must be registered in order to support the custom lifetime of that
+ *         annotation.
+ *   </ul>
+ *
+ * @author cgruber@google.com (Christian Gruber)
+ */
+public final class DaggerAdapter {
+  /**
+   * Returns a guice module from a dagger module.
+   *
+   * <p>Note: At present, it does not honor {@code @Module(includes=...)} directives.
+   */
+  public static Module from(Object... daggerModuleObjects) {
+    // TODO(cgruber): Gather injects=, dedupe, factor out instances, instantiate the rest, and go.
+    return new DaggerCompatibilityModule(daggerModuleObjects);
+  }
+
+  /**
+   * A Module that adapts Dagger {@code @Module}-annotated types to contribute configuration
+   * to an {@link com.google.inject.Injector} using a dagger-specific
+   * {@link ModuleAnnotatedMethodScanner}.
+   */
+  private static final class DaggerCompatibilityModule implements Module {
+    private final Object[] daggerModuleObjects;
+
+    private DaggerCompatibilityModule(Object... daggerModuleObjects) {
+      this.daggerModuleObjects = daggerModuleObjects;
+    }
+
+    @Override public void configure(Binder binder) {
+      for (Object module : daggerModuleObjects) {
+        binder.install(ProviderMethodsModule.forModule(module, DaggerMethodScanner.INSTANCE));
+      }
+    }
+
+    @Override public String toString() {
+      return Objects.toStringHelper(this)
+          .add("modules", Arrays.asList(daggerModuleObjects))
+          .toString();
+    }
+  }
+
+  private DaggerAdapter() {}
+}
diff --git a/extensions/dagger-adapter/src/com/google/inject/daggeradapter/DaggerMethodScanner.java b/extensions/dagger-adapter/src/com/google/inject/daggeradapter/DaggerMethodScanner.java
new file mode 100644
index 0000000..0dbdda2
--- /dev/null
+++ b/extensions/dagger-adapter/src/com/google/inject/daggeradapter/DaggerMethodScanner.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 2015 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.inject.daggeradapter;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.internal.UniqueAnnotations;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ModuleAnnotatedMethodScanner;
+
+import dagger.Provides;
+import dagger.Provides.Type;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * A scanner to process provider methods on Dagger modules.
+ *
+ * @author cgruber@google.com (Christian Gruber)
+ */
+final class DaggerMethodScanner extends ModuleAnnotatedMethodScanner {
+  static DaggerMethodScanner INSTANCE = new DaggerMethodScanner();
+
+  @Override public Set<? extends Class<? extends Annotation>> annotationClasses() {
+    return ImmutableSet.of(dagger.Provides.class);
+  }
+
+  @Override public <T> Key<T> prepareMethod(
+      Binder binder, Annotation rawAnnotation, Key<T> key, InjectionPoint injectionPoint) {
+    Method providesMethod = (Method) injectionPoint.getMember();
+    Provides annotation = (Provides) rawAnnotation;
+    switch (annotation.type()) {
+      case UNIQUE:
+        return key;
+      case MAP:
+        /* TODO(cgruber) implement map bindings */
+        binder.addError("Map bindings are not yet supported.");
+      case SET:
+        return processSetBinding(binder, key);
+      case SET_VALUES:
+        binder.addError(Type.SET_VALUES.name() + " contributions are not supported by Guice.",
+            providesMethod);
+        return key;
+      default:
+        binder.addError("Unknown @Provides type " + annotation.type() + ".", providesMethod);
+        return key;
+    }
+  }
+
+  private static <T> Key<T> processSetBinding(Binder binder, Key<T> key) {
+    Multibinder<T> setBinder = Multibinder.newSetBinder(binder, key.getTypeLiteral());
+    Key<T> newKey = Key.get(key.getTypeLiteral(), UniqueAnnotations.create());
+    setBinder.addBinding().to(newKey);
+    return newKey;
+  }
+
+  private DaggerMethodScanner() {}
+}
\ No newline at end of file
diff --git a/extensions/dagger-adapter/test/com/google/inject/daggeradapter/DaggerAdapterTest.java b/extensions/dagger-adapter/test/com/google/inject/daggeradapter/DaggerAdapterTest.java
new file mode 100644
index 0000000..30e1d18
--- /dev/null
+++ b/extensions/dagger-adapter/test/com/google/inject/daggeradapter/DaggerAdapterTest.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2015 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.inject.daggeradapter;
+
+import static dagger.Provides.Type.SET;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.util.Set;
+
+/**
+ * Tests for {@link DaggerAdapter}.
+ *
+ * @author cgruber@google.com (Christian Gruber)
+ */
+
+public class DaggerAdapterTest extends TestCase {
+  @dagger.Module static class SimpleDaggerModule {
+    @dagger.Provides Integer anInteger() {
+      return 1;
+    }
+  }
+
+  public void testSimpleModule() {
+    Injector i = Guice.createInjector(DaggerAdapter.from(new SimpleDaggerModule()));
+    assertEquals((Integer) 1, i.getInstance(Integer.class));
+  }
+
+  static class SimpleGuiceModule extends AbstractModule {
+    @Provides String aString(Integer i) {
+      return i.toString();
+    }
+    @Override protected void configure() {}
+  }
+
+  public void testInteractionWithGuiceModules() {
+     Injector i = Guice.createInjector(
+         new SimpleGuiceModule(),
+         DaggerAdapter.from(new SimpleDaggerModule()));
+     assertEquals("1", i.getInstance(String.class));
+  }
+
+  @dagger.Module static class SetBindingDaggerModule1 {
+    @dagger.Provides(type=SET) Integer anInteger() {
+      return 5;
+    }
+  }
+
+  @dagger.Module static class SetBindingDaggerModule2 {
+    @dagger.Provides(type=SET) Integer anInteger() {
+      return 3;
+    }
+  }
+
+  public void testSetBindings() {
+    Injector i = Guice.createInjector(
+        DaggerAdapter.from(new SetBindingDaggerModule1(), new SetBindingDaggerModule2()));
+    assertEquals(ImmutableSet.of(3, 5), i.getInstance(new Key<Set<Integer>>() {}));
+  }
+
+  static class MultibindingGuiceModule implements Module {
+    @Override public void configure(Binder binder) {
+      Multibinder<Integer> mb = Multibinder.newSetBinder(binder, Integer.class);
+      mb.addBinding().toInstance(13);
+      mb.addBinding().toProvider(Providers.of(8)); // mix'n'match.
+    }
+  }
+
+  public void testSetBindingsWithGuiceModule() {
+    Injector i = Guice.createInjector(
+        new MultibindingGuiceModule(),
+        DaggerAdapter.from(new SetBindingDaggerModule1(), new SetBindingDaggerModule2()));
+    assertEquals(ImmutableSet.of(13, 3, 5, 8), i.getInstance(new Key<Set<Integer>>() {}));
+  }
+}
diff --git a/extensions/grapher/build.properties b/extensions/grapher/build.properties
new file mode 100644
index 0000000..1461d3c
--- /dev/null
+++ b/extensions/grapher/build.properties
@@ -0,0 +1,7 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.grapher.AllTests
+module=com.google.inject.grapher
+fragment=true
diff --git a/extensions/grapher/build.xml b/extensions/grapher/build.xml
new file mode 100644
index 0000000..77f2983
--- /dev/null
+++ b/extensions/grapher/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-grapher" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/grapher/pom.xml b/extensions/grapher/pom.xml
new file mode 100644
index 0000000..715f80d
--- /dev/null
+++ b/extensions/grapher/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-grapher</artifactId>
+
+  <name>Google Guice - Extensions - Grapher</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.inject.extensions</groupId>
+      <artifactId>guice-assistedinject</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.inject.extensions</groupId>
+      <artifactId>guice-multibindings</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>3.0</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/extensions/grapher/src/com/google/inject/grapher/AbstractInjectorGrapher.java b/extensions/grapher/src/com/google/inject/grapher/AbstractInjectorGrapher.java
new file mode 100644
index 0000000..940caab
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/AbstractInjectorGrapher.java
@@ -0,0 +1,228 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Abstract injector grapher that builds the dependency graph but doesn't render it.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public abstract class AbstractInjectorGrapher implements InjectorGrapher {
+  private final RootKeySetCreator rootKeySetCreator;
+  private final AliasCreator aliasCreator;
+  private final NodeCreator nodeCreator;
+  private final EdgeCreator edgeCreator;
+
+  /**
+   * Parameters used to override default settings of the grapher.
+   * @since 4.0
+   */
+  public static final class GrapherParameters {
+    private RootKeySetCreator rootKeySetCreator = new DefaultRootKeySetCreator();
+    private AliasCreator aliasCreator = new ProviderAliasCreator();
+    private NodeCreator nodeCreator = new DefaultNodeCreator();
+    private EdgeCreator edgeCreator = new DefaultEdgeCreator();
+
+    public RootKeySetCreator getRootKeySetCreator() {
+      return rootKeySetCreator;
+    }
+
+    public GrapherParameters setRootKeySetCreator(RootKeySetCreator rootKeySetCreator) {
+      this.rootKeySetCreator = rootKeySetCreator;
+      return this;
+    }
+
+    public AliasCreator getAliasCreator() {
+      return aliasCreator;
+    }
+
+    public GrapherParameters setAliasCreator(AliasCreator aliasCreator) {
+      this.aliasCreator = aliasCreator;
+      return this;
+    }
+
+    public NodeCreator getNodeCreator() {
+      return nodeCreator;
+    }
+
+    public GrapherParameters setNodeCreator(NodeCreator nodeCreator) {
+      this.nodeCreator = nodeCreator;
+      return this;
+    }
+
+    public EdgeCreator getEdgeCreator() {
+      return edgeCreator;
+    }
+
+    public GrapherParameters setEdgeCreator(EdgeCreator edgeCreator) {
+      this.edgeCreator = edgeCreator;
+      return this;
+    }
+  }
+
+  public AbstractInjectorGrapher() {
+    this(new GrapherParameters());
+  }
+
+  public AbstractInjectorGrapher(GrapherParameters options) {
+    this.rootKeySetCreator = options.getRootKeySetCreator();
+    this.aliasCreator = options.getAliasCreator();
+    this.nodeCreator = options.getNodeCreator();
+    this.edgeCreator = options.getEdgeCreator();
+  }
+
+  @Override public final void graph(Injector injector) throws IOException {
+    graph(injector, rootKeySetCreator.getRootKeys(injector));
+  }
+
+  @Override public final void graph(Injector injector, Set<Key<?>> root) throws IOException {
+    reset();
+
+    Iterable<Binding<?>> bindings = getBindings(injector, root);
+    Map<NodeId, NodeId> aliases = resolveAliases(aliasCreator.createAliases(bindings));
+    createNodes(nodeCreator.getNodes(bindings), aliases);
+    createEdges(edgeCreator.getEdges(bindings), aliases);
+    postProcess();
+  }
+
+  /** Resets the state of the grapher before rendering a new graph. */
+  protected abstract void reset() throws IOException;
+
+  /** Adds a new interface node to the graph. */
+  protected abstract void newInterfaceNode(InterfaceNode node) throws IOException;
+
+  /** Adds a new implementation node to the graph. */
+  protected abstract void newImplementationNode(ImplementationNode node) throws IOException;
+
+  /** Adds a new instance node to the graph. */
+  protected abstract void newInstanceNode(InstanceNode node) throws IOException;
+
+  /** Adds a new dependency edge to the graph. */
+  protected abstract void newDependencyEdge(DependencyEdge edge) throws IOException;
+
+  /** Adds a new binding edge to the graph. */
+  protected abstract void newBindingEdge(BindingEdge edge) throws IOException;
+
+  /** Performs any post processing required after all nodes and edges have been added. */
+  protected abstract void postProcess() throws IOException;
+
+  private void createNodes(Iterable<Node> nodes, Map<NodeId, NodeId> aliases) throws IOException {
+    for (Node node : nodes) {
+      NodeId originalId = node.getId();
+      NodeId resolvedId = resolveAlias(aliases, originalId);
+      node = node.copy(resolvedId);
+
+      // Only render nodes that aren't aliased to some other node.
+      if (resolvedId.equals(originalId)) {
+        if (node instanceof InterfaceNode) {
+          newInterfaceNode((InterfaceNode) node);
+        } else if (node instanceof ImplementationNode) {
+          newImplementationNode((ImplementationNode) node);
+        } else {
+          newInstanceNode((InstanceNode) node);
+        }
+      }
+    }
+  }
+
+  private void createEdges(Iterable<Edge> edges, Map<NodeId, NodeId> aliases) throws IOException {
+    for (Edge edge : edges) {
+      edge = edge.copy(resolveAlias(aliases, edge.getFromId()),
+          resolveAlias(aliases, edge.getToId()));
+      if (!edge.getFromId().equals(edge.getToId())) {
+        if (edge instanceof BindingEdge) {
+          newBindingEdge((BindingEdge) edge);
+        } else {
+          newDependencyEdge((DependencyEdge) edge);
+        }
+      }
+    }
+  }
+
+  private NodeId resolveAlias(Map<NodeId, NodeId> aliases, NodeId nodeId) {
+    return aliases.containsKey(nodeId) ? aliases.get(nodeId) : nodeId;
+  }
+
+  /**
+   * Transitively resolves aliases. Given aliases (X to Y) and (Y to Z), it will return mappings
+   * (X to Z) and (Y to Z).
+   */
+  private Map<NodeId, NodeId> resolveAliases(Iterable<Alias> aliases) {
+    Map<NodeId, NodeId> resolved = Maps.newHashMap();
+    Map<NodeId, Set<NodeId>> inverse = Maps.newHashMap();
+
+    for (Alias alias : aliases) {
+      NodeId from = alias.getFromId();
+      NodeId to = alias.getToId();
+      if (resolved.containsKey(to)) {
+        to = resolved.get(to);
+      }
+      resolved.put(from, to);
+      if (inverse.get(to) == null) {
+        inverse.put(to, Sets.<NodeId>newHashSet());
+      }
+      inverse.get(to).add(from);
+
+      Set<NodeId> prev = inverse.get(from);
+      if (prev != null) {
+        for (NodeId id : prev) {
+          resolved.remove(id);
+          inverse.get(from).remove(id);
+          resolved.put(id, to);
+          inverse.get(to).add(id);
+        }
+      }
+    }
+
+    return resolved;
+  }
+
+  /** Returns the bindings for the root keys and their transitive dependencies. */
+  private Iterable<Binding<?>> getBindings(Injector injector, Set<Key<?>> root) {
+    Set<Key<?>> keys = Sets.newHashSet(root);
+    Set<Key<?>> visitedKeys = Sets.newHashSet();
+    List<Binding<?>> bindings = Lists.newArrayList();
+    TransitiveDependencyVisitor keyVisitor = new TransitiveDependencyVisitor();
+
+    while (!keys.isEmpty()) {
+      Iterator<Key<?>> iterator = keys.iterator();
+      Key<?> key = iterator.next();
+      iterator.remove();
+
+      if (!visitedKeys.contains(key)) {
+        Binding<?> binding = injector.getBinding(key);
+        bindings.add(binding);
+        visitedKeys.add(key);
+        keys.addAll(binding.acceptTargetVisitor(keyVisitor));
+      }
+    }
+    return bindings;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/Alias.java b/extensions/grapher/src/com/google/inject/grapher/Alias.java
new file mode 100644
index 0000000..bc20ca9
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/Alias.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+/**
+ * Alias between two nodes. Causes the 'from' node to be aliased with the 'to' node, which means
+ * that the 'from' node is not rendered and all edges going to it instead go to the 'to' node.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public final class Alias {
+  private final NodeId fromId;
+  private final NodeId toId;
+
+  public Alias(NodeId fromId, NodeId toId) {
+    this.fromId = fromId;
+    this.toId = toId;
+  }
+
+  public NodeId getFromId() {
+    return fromId;
+  }
+
+  public NodeId getToId() {
+    return toId;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/AliasCreator.java b/extensions/grapher/src/com/google/inject/grapher/AliasCreator.java
new file mode 100644
index 0000000..cd428ac
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/AliasCreator.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.inject.Binding;
+
+/**
+ * Creator of node aliases. Used by dependency graphers to merge nodes in the internal Guice graph
+ * into a single node on the rendered graph.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public interface AliasCreator {
+  /**
+   * Returns aliases for the given dependency graph. The aliases do not need to be transitively
+   * resolved, i.e. it is valid to return an alias (X to Y) and an alias (Y to Z). It is the
+   * responsibility of the caller to resolve this to (X to Z) and (Y to Z).
+   *
+   * @param bindings bindings that make up the dependency graph
+   * @return aliases that should be applied on the graph
+   */
+  Iterable<Alias> createAliases(Iterable<Binding<?>> bindings);
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/BindingEdge.java b/extensions/grapher/src/com/google/inject/grapher/BindingEdge.java
new file mode 100644
index 0000000..92d72ba
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/BindingEdge.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import com.google.common.base.Objects;
+
+/**
+ * Edge that connects an interface to the type or instance that is bound to implement it.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ * @since 4.0 (since 2.0 as an interface)
+ */
+public class BindingEdge extends Edge {
+  /**
+   * Classification for what kind of binding this edge represents.
+   */
+  public enum Type {
+    /** Binding is to an instance or class of the binding's same type. */
+    NORMAL,
+    /** Binding is to an instance or class that provides the binding's type. */
+    PROVIDER,
+    /** Binding is to the interface for a constant of a different type. */
+    CONVERTED_CONSTANT
+  }
+
+  private final Type type;
+
+  public BindingEdge(NodeId fromId, NodeId toId, Type type) {
+    super(fromId, toId);
+    this.type = type;
+  }
+
+  public Type getType() {
+    return type;
+  }
+
+  @Override public boolean equals(Object obj) {
+    if (!(obj instanceof BindingEdge)) {
+      return false;
+    }
+    BindingEdge other = (BindingEdge) obj;
+    return super.equals(other) && Objects.equal(type, other.type);
+  }
+
+  @Override public int hashCode() {
+    return 31 * super.hashCode() + Objects.hashCode(type);
+  }
+
+  @Override public String toString() {
+    return "BindingEdge{fromId=" + getFromId() + " toId=" + getToId() + " type=" + type + "}";
+  }
+
+  @Override public Edge copy(NodeId fromId, NodeId toId) {
+    return new BindingEdge(fromId, toId, type);
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/DefaultEdgeCreator.java b/extensions/grapher/src/com/google/inject/grapher/DefaultEdgeCreator.java
new file mode 100644
index 0000000..5ba402d
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/DefaultEdgeCreator.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.inject.Binding;
+import com.google.inject.spi.ConstructorBinding;
+import com.google.inject.spi.ConvertedConstantBinding;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.LinkedKeyBinding;
+import com.google.inject.spi.ProviderBinding;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderKeyBinding;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Default edge creator.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ */
+final class DefaultEdgeCreator implements EdgeCreator {
+
+  @Override public Iterable<Edge> getEdges(Iterable<Binding<?>> bindings) {
+    List<Edge> edges = Lists.newArrayList();
+    EdgeVisitor visitor = new EdgeVisitor();
+    for (Binding<?> binding : bindings) {
+      edges.addAll(binding.acceptTargetVisitor(visitor));
+    }
+    return edges;
+  }
+
+  /**
+   * {@link BindingTargetVisitor} that adds edges to the graph based on the visited {@link Binding}.
+   */
+  private static final class EdgeVisitor
+      extends DefaultBindingTargetVisitor<Object, Collection<Edge>> {
+
+    /**
+     * Returns a dependency edge for each {@link Dependency} in the binding. These will be from the
+     * given node ID to the {@link Dependency}'s {@link Key}.
+     *
+     * @param nodeId ID of the node that should be the tail of the dependency
+     *     edges
+     * @param binding {@link Binding} for the dependencies
+     */
+    private <T extends Binding<?> & HasDependencies> Collection<Edge> newDependencyEdges(
+        NodeId nodeId, T binding) {
+      ImmutableList.Builder<Edge> builder = ImmutableList.builder();
+      for (Dependency<?> dependency : binding.getDependencies()) {
+        NodeId to = NodeId.newTypeId(dependency.getKey());
+        builder.add(new DependencyEdge(nodeId, to, dependency.getInjectionPoint()));
+      }
+      return builder.build();
+    }
+
+    /**
+     * Visitor for {@link ConstructorBinding}s. These are for classes that Guice will instantiate to
+     * satisfy injection requests.
+     */
+    @Override public Collection<Edge> visit(ConstructorBinding<?> binding) {
+      return newDependencyEdges(NodeId.newTypeId(binding.getKey()), binding);
+    }
+
+    /**
+     * Visitor for {@link ConvertedConstantBinding}. The {@link Binding}'s {@link Key} will be of an
+     * annotated primitive type, and the value of {@link ConvertedConstantBinding#getSourceKey()}
+     * will be of a {@link String} with the same annotation.
+     */
+    @Override public Collection<Edge> visit(ConvertedConstantBinding<?> binding) {
+      return ImmutableList.<Edge>of(new BindingEdge(NodeId.newTypeId(binding.getKey()),
+          NodeId.newTypeId(binding.getSourceKey()),
+          BindingEdge.Type.CONVERTED_CONSTANT));
+    }
+
+    /**
+     * Visitor for {@link InstanceBinding}. We then render any dependency edgess that the instance
+     * may have, which come either from {@link InjectionPoint}s (method and field) on the instance,
+     * or on {@link Dependency}s the instance declares through the {@link HasDependencies}
+     * interface.
+     */
+    @Override public Collection<Edge> visit(InstanceBinding<?> binding) {
+      return new ImmutableList.Builder<Edge>()
+          .add(new BindingEdge(NodeId.newTypeId(binding.getKey()),
+              NodeId.newInstanceId(binding.getKey()),
+              BindingEdge.Type.NORMAL))
+          .addAll(newDependencyEdges(NodeId.newInstanceId(binding.getKey()), binding))
+          .build();
+    }
+
+    /**
+     * Visitor for {@link LinkedKeyBinding}. This is the standard {@link Binding} you get from
+     * binding an interface class to an implementation class. We  draw a {@link BindingEdge} from
+     * the interface node to the node of the implementing class.
+     */
+    @Override public Collection<Edge> visit(LinkedKeyBinding<?> binding) {
+      return ImmutableList.<Edge>of(new BindingEdge(NodeId.newTypeId(binding.getKey()),
+          NodeId.newTypeId(binding.getLinkedKey()),
+          BindingEdge.Type.NORMAL));
+    }
+
+    /**
+     * Visitor for {@link ProviderBinding}. These {@link Binding}s arise from an
+     * {@link InjectionPoint} for the {@link Provider} interface.
+     */
+    @Override public Collection<Edge> visit(ProviderBinding<?> binding) {
+      return ImmutableList.<Edge>of(new BindingEdge(NodeId.newTypeId(binding.getKey()),
+          NodeId.newTypeId(binding.getProvidedKey()), BindingEdge.Type.PROVIDER));
+    }
+
+    /**
+     * Same as {@link #visit(InstanceBinding)}, but the binding edge is
+     * {@link BindingEdge.Type#PROVIDER}.
+     */
+    @Override public Collection<Edge> visit(ProviderInstanceBinding<?> binding) {
+      return new ImmutableList.Builder<Edge>()
+          .add(new BindingEdge(NodeId.newTypeId(binding.getKey()),
+              NodeId.newInstanceId(binding.getKey()), BindingEdge.Type.PROVIDER))
+          .addAll(newDependencyEdges(NodeId.newInstanceId(binding.getKey()), binding))
+          .build();
+    }
+
+    /**
+     * Same as {@link #visit(LinkedKeyBinding)}, but the binding edge is
+     * {@link BindingEdge.Type#PROVIDER}.
+     */
+    @Override public Collection<Edge> visit(ProviderKeyBinding<?> binding) {
+      return ImmutableList.<Edge>of(new BindingEdge(NodeId.newTypeId(binding.getKey()),
+          NodeId.newTypeId(binding.getProviderKey()), BindingEdge.Type.PROVIDER));
+    }
+
+    @Override public Collection<Edge> visitOther(Binding<?> binding) {
+      return ImmutableList.of();
+    }
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/DefaultNodeCreator.java b/extensions/grapher/src/com/google/inject/grapher/DefaultNodeCreator.java
new file mode 100644
index 0000000..e97f111
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/DefaultNodeCreator.java
@@ -0,0 +1,131 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.inject.Binding;
+import com.google.inject.spi.ConstructorBinding;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.ProviderInstanceBinding;
+
+import java.lang.reflect.Member;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Default node creator.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ */
+final class DefaultNodeCreator implements NodeCreator {
+  @Override public Iterable<Node> getNodes(Iterable<Binding<?>> bindings) {
+    List<Node> nodes = Lists.newArrayList();
+    NodeVisitor visitor = new NodeVisitor();
+    for (Binding<?> binding : bindings) {
+      nodes.addAll(binding.acceptTargetVisitor(visitor));
+    }
+    return nodes;
+  }
+
+  /**
+   * {@link BindingTargetVisitor} that adds nodes to the graph based on the visited {@link Binding}.
+   */
+  private static final class NodeVisitor
+      extends DefaultBindingTargetVisitor<Object, Collection<Node>> {
+
+    /** Returns a new interface node for the given {@link Binding}. */
+    private InterfaceNode newInterfaceNode(Binding<?> binding) {
+      return new InterfaceNode(NodeId.newTypeId(binding.getKey()), binding.getSource());
+    }
+
+    /**
+     * Returns a new implementation node for the given binding.
+     *
+     * @param binding binding for the node to create
+     * @param members members to add to the node
+     * @return implementation node for the given binding
+     */
+    private ImplementationNode newImplementationNode(Binding<?> binding,
+        Collection<Member> members) {
+      return new ImplementationNode(NodeId.newTypeId(binding.getKey()), binding.getSource(),
+          members);
+    }
+
+    /**
+     * Returns a new instance node for the given {@link Binding}.
+     *
+     * @param binding binding for the node to create
+     * @param instance value of the instance
+     * @return instance node for the given binding
+     */
+    private <T extends Binding<?> & HasDependencies> InstanceNode newInstanceNode(T binding,
+        Object instance) {
+      Collection<Member> members = Lists.newArrayList();
+      for (Dependency<?> dependency : binding.getDependencies()) {
+        InjectionPoint injectionPoint = dependency.getInjectionPoint();
+
+        if (injectionPoint != null) {
+          members.add(injectionPoint.getMember());
+        }
+      }
+      return new InstanceNode(NodeId.newInstanceId(binding.getKey()), binding.getSource(), instance,
+          members);
+    }
+
+    /**
+     * Visitor for {@link ConstructorBinding}s. These are for classes that Guice will instantiate to
+     * satisfy injection requests.
+     */
+    @Override public Collection<Node> visit(ConstructorBinding<?> binding) {
+      Collection<Member> members = Lists.newArrayList();
+      members.add(binding.getConstructor().getMember());
+      for (InjectionPoint injectionPoint : binding.getInjectableMembers()) {
+        members.add(injectionPoint.getMember());
+      }
+
+      return ImmutableList.<Node>of(newImplementationNode(binding, members));
+    }
+
+    /**
+     * Visitor for {@link InstanceBinding}. We render two nodes in this case: an interface node for
+     * the binding's {@link Key}, and then an implementation node for the instance {@link Object}
+     * itself.
+     */
+    @Override public Collection<Node> visit(InstanceBinding<?> binding) {
+      return ImmutableList.<Node>of(newInterfaceNode(binding), newInstanceNode(binding,
+          binding.getInstance()));
+    }
+
+    /**
+     * Same as {@link #visit(InstanceBinding)}, but the binding edge is
+     * {@link BindingEdgeType#PROVIDER}.
+     */
+    @Override public Collection<Node> visit(ProviderInstanceBinding<?> binding) {
+      return ImmutableList.<Node>of(newInterfaceNode(binding), newInstanceNode(binding,
+          binding.getUserSuppliedProvider()));
+    }
+
+    @Override public Collection<Node> visitOther(Binding<?> binding) {
+      return ImmutableList.<Node>of(newInterfaceNode(binding));
+    }
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/DefaultRootKeySetCreator.java b/extensions/grapher/src/com/google/inject/grapher/DefaultRootKeySetCreator.java
new file mode 100644
index 0000000..cf44d46
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/DefaultRootKeySetCreator.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Root key set creator that starts with all types that are not Guice internal types or the
+ * {@link Logger} type.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public class DefaultRootKeySetCreator implements RootKeySetCreator {
+  private static final Key<Logger> loggerKey = Key.get(Logger.class);
+
+  @Override public Set<Key<?>> getRootKeys(Injector injector) {
+    Set<Key<?>> root = Sets.newHashSet();
+    for (Key<?> key : injector.getBindings().keySet()) {
+      if (key.getTypeLiteral().getRawType().getPackage() != Guice.class.getPackage()
+        && !loggerKey.equals(key)) {
+        root.add(key);
+      }
+    }
+    return root;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/DependencyEdge.java b/extensions/grapher/src/com/google/inject/grapher/DependencyEdge.java
new file mode 100644
index 0000000..a8fe7bb
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/DependencyEdge.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import com.google.common.base.Objects;
+import com.google.inject.spi.InjectionPoint;
+
+/**
+ * Edge from a class or {@link InjectionPoint} to the interface node that will satisfy the
+ * dependency.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ * @since 4.0 (since 2.0 as an interface)
+ */
+public class DependencyEdge extends Edge {
+  /**
+   * Injection point to which this dependency belongs, or null if the dependency isn't attached to a
+   * particular injection point.
+   */
+  private final InjectionPoint injectionPoint;
+
+  public DependencyEdge(NodeId fromId, NodeId toId, InjectionPoint injectionPoint) {
+    super(fromId, toId);
+    this.injectionPoint = injectionPoint;
+  }
+
+  public InjectionPoint getInjectionPoint() {
+    return injectionPoint;
+  }
+
+  @Override public boolean equals(Object obj) {
+    if (!(obj instanceof DependencyEdge)) {
+      return false;
+    }
+    DependencyEdge other = (DependencyEdge) obj;
+    return super.equals(other) && Objects.equal(injectionPoint, other.injectionPoint);
+  }
+
+  @Override public int hashCode() {
+    return 31 * super.hashCode() + Objects.hashCode(injectionPoint);
+  }
+
+  @Override public String toString() {
+    return "DependencyEdge{fromId=" + getFromId() + " toId=" + getToId()
+        + " injectionPoint=" + injectionPoint + "}";
+  }
+
+  @Override public Edge copy(NodeId fromId, NodeId toId) {
+    return new DependencyEdge(fromId, toId, injectionPoint);
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/Edge.java b/extensions/grapher/src/com/google/inject/grapher/Edge.java
new file mode 100644
index 0000000..40a3df0
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/Edge.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.base.Objects;
+
+/**
+ * Edge in a guice dependency graph.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public abstract class Edge {
+  private final NodeId fromId;
+  private final NodeId toId;
+
+  protected Edge(NodeId fromId, NodeId toId) {
+    this.fromId = fromId;
+    this.toId = toId;
+  }
+
+  public NodeId getFromId() {
+    return fromId;
+  }
+
+  public NodeId getToId() {
+    return toId;
+  }
+
+  @Override public boolean equals(Object obj) {
+    if (!(obj instanceof Edge)) {
+      return false;
+    }
+    Edge other = (Edge) obj;
+    return Objects.equal(fromId, other.fromId) && Objects.equal(toId, other.toId);
+  }
+
+  @Override public int hashCode() {
+    return Objects.hashCode(fromId, toId);
+  }
+
+  /**
+   * Returns a copy of the edge with new node IDs.
+   *
+   * @param fromId new ID of the 'from' node
+   * @param toId new ID of the 'to' node
+   * @return copy of the edge with the new node IDs
+   */
+  public abstract Edge copy(NodeId fromId, NodeId toId);
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/EdgeCreator.java b/extensions/grapher/src/com/google/inject/grapher/EdgeCreator.java
new file mode 100644
index 0000000..f14e71f
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/EdgeCreator.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.inject.Binding;
+
+/**
+ * Creator of graph edges to render. All edges will be rendered on the graph after node aliasing is
+ * performed.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public interface EdgeCreator {
+
+  /** Returns edges for the given dependency graph. */
+  Iterable<Edge> getEdges(Iterable<Binding<?>> bindings);
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/ImplementationNode.java b/extensions/grapher/src/com/google/inject/grapher/ImplementationNode.java
new file mode 100644
index 0000000..424ee1a
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/ImplementationNode.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import com.google.common.base.Objects;
+import java.lang.reflect.Member;
+import java.util.Collection;
+
+/**
+ * Node for types that have {@link com.google.inject.spi.Dependency}s and are
+ * bound to {@link InterfaceNode}s. These nodes will often have fields for
+ * {@link Member}s that are {@link com.google.inject.spi.InjectionPoint}s.
+ *
+ * @see DependencyEdge
+ * @author phopkins@gmail.com (Pete Hopkins)
+ * @since 4.0 (since 2.0 as an interface)
+ */
+public class ImplementationNode extends Node {
+  private final Collection<Member> members;
+
+  public ImplementationNode(NodeId id, Object source, Collection<Member> members) {
+    super(id, source);
+    this.members = members;
+  }
+
+  public Collection<Member> getMembers() {
+    return members;
+  }
+
+  @Override public boolean equals(Object obj) {
+    if (!(obj instanceof ImplementationNode)) {
+      return false;
+    }
+    ImplementationNode other = (ImplementationNode) obj;
+    return super.equals(other) && Objects.equal(members, other.members);
+  }
+
+  @Override public int hashCode() {
+    return 31 * super.hashCode() + Objects.hashCode(members);
+  }
+
+  @Override public String toString() {
+    return "ImplementationNode{id=" + getId() + " source=" + getSource()
+        + " members=" + members + "}";
+  }
+
+  @Override public Node copy(NodeId id) {
+    return new ImplementationNode(id, getSource(), getMembers());
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/InjectorGrapher.java b/extensions/grapher/src/com/google/inject/grapher/InjectorGrapher.java
new file mode 100644
index 0000000..2d9efcd
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/InjectorGrapher.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import com.google.inject.Injector;
+import com.google.inject.Key;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Guice injector grapher. Renders the guice dependency graph for an injector. It can render the
+ * whole dependency graph or just transitive dependencies of a given set of nodes.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ * @since 4.0 (since 2.0 as a concrete class with a different API)
+ */
+public interface InjectorGrapher {
+
+  /**
+   * Graphs the guice dependency graph for the given injector using default starting keys.
+   */
+  void graph(Injector injector) throws IOException;
+
+  /**
+   * Graphs the guice dependency graph for the given injector using the given starting keys and
+   * their transitive dependencies.
+   */
+  void graph(Injector injector, Set<Key<?>> root) throws IOException;
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/InstanceNode.java b/extensions/grapher/src/com/google/inject/grapher/InstanceNode.java
new file mode 100644
index 0000000..0aaa19b
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/InstanceNode.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.base.Objects;
+import java.lang.reflect.Member;
+
+/**
+ * Node for instances. Used when a type is bound to an instance.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public class InstanceNode extends Node {
+  private final Object instance;
+  private final Iterable<Member> members;
+
+  public InstanceNode(NodeId id, Object source, Object instance, Iterable<Member> members) {
+    super(id, source);
+    this.instance = instance;
+    this.members = members;
+  }
+
+  public Object getInstance() {
+    return instance;
+  }
+
+  public Iterable<Member> getMembers() {
+    return members;
+  }
+
+  @Override public boolean equals(Object obj) {
+    if (!(obj instanceof InstanceNode)) {
+      return false;
+    }
+    InstanceNode other = (InstanceNode) obj;
+    return super.equals(other) && Objects.equal(instance, other.instance)
+        && Objects.equal(members, other.members);
+  }
+
+  @Override public int hashCode() {
+    return 31 * super.hashCode() + Objects.hashCode(instance, members);
+  }
+
+  @Override public String toString() {
+    return "InstanceNode{id=" + getId() + " source=" + getSource() + " instance=" + instance
+        + " members=" + members + "}";
+  }
+
+  @Override public Node copy(NodeId id) {
+    return new InstanceNode(id, getSource(), getInstance(), getMembers());
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/InterfaceNode.java b/extensions/grapher/src/com/google/inject/grapher/InterfaceNode.java
new file mode 100644
index 0000000..c23008d
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/InterfaceNode.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+/**
+ * Node for an interface type that has been bound to an implementation class or instance.
+ *
+ * @see BindingEdge
+ * @author phopkins@gmail.com (Pete Hopkins)
+ * @since 4.0 (since 2.0 as an interface)
+ */
+public class InterfaceNode extends Node {
+  public InterfaceNode(NodeId id, Object source) {
+    super(id, source);
+  }
+
+  @Override public Node copy(NodeId id) {
+    return new InterfaceNode(id, getSource());
+  }
+
+  @Override public boolean equals(Object obj) {
+    return (obj instanceof InterfaceNode) && super.equals(obj);
+  }
+
+  @Override public String toString() {
+    return "InterfaceNode{id=" + getId() + " source=" + getSource() + "}";
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/NameFactory.java b/extensions/grapher/src/com/google/inject/grapher/NameFactory.java
new file mode 100644
index 0000000..20e740a
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/NameFactory.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import com.google.inject.Key;
+
+import java.lang.reflect.Member;
+
+/**
+ * Interface for a service that provides nice {@link String}s that we can
+ * display in the graph for the types that come up in
+ * {@link com.google.inject.Binding}s.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public interface NameFactory {
+  String getMemberName(Member member);
+  String getClassName(Key<?> key);
+  String getInstanceName(Object instance);
+  String getAnnotationName(Key<?> key);
+  String getSourceName(Object source);
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/Node.java b/extensions/grapher/src/com/google/inject/grapher/Node.java
new file mode 100644
index 0000000..ace85a5
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/Node.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.base.Objects;
+
+/**
+ * Node in a guice dependency graph.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public abstract class Node {
+  /**
+   * When set to true, the source object is ignored in {@link #equals} and {@link #hashCode}.
+   * Only used in tests.
+   */
+  static boolean ignoreSourceInComparisons = false;
+
+  private final NodeId id;
+  private final Object source;
+
+  protected Node(NodeId id, Object source) {
+    this.id = id;
+    this.source = source;
+  }
+
+  public NodeId getId() {
+    return id;
+  }
+
+  public Object getSource() {
+    return source;
+  }
+
+  @Override public boolean equals(Object obj) {
+    if (!(obj instanceof Node)) {
+      return false;
+    }
+    Node other = (Node) obj;
+    return Objects.equal(id, other.id)
+        && (ignoreSourceInComparisons || Objects.equal(source, other.source));
+  }
+
+  @Override public int hashCode() {
+    return ignoreSourceInComparisons ? id.hashCode() : Objects.hashCode(id, source);
+  }
+
+  /**
+   * Returns a copy of the node with a new ID.
+   *
+   * @param id new ID of the node
+   * @return copy of the node with a new ID
+   */
+  public abstract Node copy(NodeId id);
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/NodeCreator.java b/extensions/grapher/src/com/google/inject/grapher/NodeCreator.java
new file mode 100644
index 0000000..d448370
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/NodeCreator.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.inject.Binding;
+
+/**
+ * Creator of graph nodes.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public interface NodeCreator {
+
+  /** Returns nodes for the given dependency graph. */
+  Iterable<Node> getNodes(Iterable<Binding<?>> bindings);
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/NodeId.java b/extensions/grapher/src/com/google/inject/grapher/NodeId.java
new file mode 100644
index 0000000..33df33d
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/NodeId.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.base.Objects;
+import com.google.inject.Key;
+
+/**
+ * ID of a node in the graph. An ID is given by a {@link Key} and a node type, which is used to
+ * distinguish instances and implementation classes for the same key. For example
+ * {@code bind(Integer.class).toInstance(42)} produces two nodes: an
+ * interface node with the key of {@code Key<Integer>} and an instance node with the same
+ * {@link Key} and value of 42.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public final class NodeId {
+
+  /**
+   * Type of node.
+   *
+   * @since 4.0
+   */
+  public enum NodeType {
+    /** Type or class node. */
+    TYPE,
+
+    /** Instance node, used when something is bound to an instance. */
+    INSTANCE
+  }
+
+  private final Key<?> key;
+  private final NodeType nodeType;
+
+  private NodeId(Key<?> key, NodeType nodeType) {
+    this.key = key;
+    this.nodeType = nodeType;
+  }
+
+  public static NodeId newTypeId(Key<?> key) {
+    return new NodeId(key, NodeType.TYPE);
+  }
+
+  public static NodeId newInstanceId(Key<?> key) {
+    return new NodeId(key, NodeType.INSTANCE);
+  }
+
+  public Key<?> getKey() {
+    return key;
+  }
+
+  @Override public int hashCode() {
+    return Objects.hashCode(key, nodeType);
+  }
+
+  @Override public boolean equals(Object obj) {
+    if (!(obj.getClass().equals(NodeId.class))) {
+      return false;
+    }
+    NodeId other = (NodeId) obj;
+    return Objects.equal(key, other.key) && Objects.equal(nodeType, other.nodeType);
+  }
+
+  @Override public String toString() {
+    return "NodeId{nodeType=" + nodeType + " key=" + key + "}";
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/ProviderAliasCreator.java b/extensions/grapher/src/com/google/inject/grapher/ProviderAliasCreator.java
new file mode 100644
index 0000000..d55ea7f
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/ProviderAliasCreator.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Binding;
+import com.google.inject.spi.ProviderBinding;
+import java.util.List;
+
+/**
+ * Alias creator that creates an alias for each {@link ProviderBinding}. These {@link Binding}s
+ * arise from an {@link InjectionPoint} for the {@link Provider} interface. Since this isn't
+ * very interesting information, we don't render this binding on the graph, and just alias the two
+ * nodes.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ */
+final class ProviderAliasCreator implements AliasCreator {
+  @Override public Iterable<Alias> createAliases(Iterable<Binding<?>> bindings) {
+    List<Alias> aliases = Lists.newArrayList();
+    for (Binding<?> binding : bindings) {
+      if (binding instanceof ProviderBinding) {
+        aliases.add(new Alias(NodeId.newTypeId(binding.getKey()),
+            NodeId.newTypeId(((ProviderBinding<?>) binding).getProvidedKey())));
+      }
+    }
+    return aliases;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/RootKeySetCreator.java b/extensions/grapher/src/com/google/inject/grapher/RootKeySetCreator.java
new file mode 100644
index 0000000..12114d8
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/RootKeySetCreator.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import java.util.Set;
+
+/**
+ * Creator of the default starting set of keys to graph. These keys and their transitive
+ * dependencies will be graphed.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ * @since 4.0
+ */
+public interface RootKeySetCreator {
+
+  /** Returns the set of starting keys to graph. */
+  Set<Key<?>> getRootKeys(Injector injector);
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/ShortNameFactory.java b/extensions/grapher/src/com/google/inject/grapher/ShortNameFactory.java
new file mode 100644
index 0000000..e8c6d57
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/ShortNameFactory.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.ProviderMethod;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.spi.ElementSource;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Reasonable implementation for {@link NameFactory}. Mostly takes various
+ * {@link Object#toString()}s and strips package names out of them so that
+ * they'll fit on the graph.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class ShortNameFactory implements NameFactory {
+  public String getMemberName(Member member) {
+    if (member instanceof Constructor) {
+      return "<init>";
+    } else if (member instanceof Method) {
+      return "#" + member.getName() + "(...)";
+    } else {
+      return member.getName();      
+    }
+  }
+
+  public String getAnnotationName(Key<?> key) {
+    Annotation annotation = key.getAnnotation();
+    Class<? extends Annotation> annotationType = key.getAnnotationType();
+    if (annotation != null) {
+      annotationType = annotation.annotationType();
+
+      String annotationString = annotation.toString();
+      String canonicalName = annotationType.getName();
+      String simpleName = annotationType.getSimpleName();
+ 
+      return annotationString.replace(canonicalName, simpleName).replace("()", "");
+    } else if (annotationType != null) {
+      return "@" + annotationType.getSimpleName();
+    } else {
+      return "";
+    }
+  }
+
+  public String getClassName(Key<?> key) {
+    TypeLiteral<?> typeLiteral = key.getTypeLiteral();
+    return stripPackages(typeLiteral.toString());
+  }
+
+  public String getInstanceName(Object instance) {
+    if (instance instanceof ProviderMethod) {
+      return getMethodString(((ProviderMethod<?>) instance).getMethod());
+    }
+
+    if (instance instanceof CharSequence) {
+      return "\"" + instance + "\"";
+    }
+
+    try {
+      if (instance.getClass().getMethod("toString").getDeclaringClass().equals(Object.class)) {
+        return stripPackages(instance.getClass().getName());
+      }
+    } catch (SecurityException e) {
+      throw new AssertionError(e);
+    } catch (NoSuchMethodException e) {
+      throw new AssertionError(e);
+    }
+
+    return instance.toString();
+  }
+
+  /**
+   * Returns a name for a Guice "source" object. This will typically be either
+   * a {@link StackTraceElement} for when the binding is made to the instance,
+   * or a {@link Method} when a provider method is used.
+   */
+  public String getSourceName(Object source) {
+    if (source instanceof ElementSource) {
+      source = ((ElementSource) source).getDeclaringSource();
+    }
+    if (source instanceof Method) {
+      source = StackTraceElements.forMember((Method) source);
+    }
+
+    if (source instanceof StackTraceElement) {
+      return getFileString((StackTraceElement) source);
+    }
+
+    return stripPackages(source.toString());
+  }
+
+  protected String getFileString(StackTraceElement stackTraceElement) {
+    return stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber();
+  }
+
+  protected String getMethodString(Method method) {
+    List<String> paramStrings = Lists.newArrayList();
+    for (Class<?> paramType : method.getParameterTypes()) {
+      paramStrings.add(paramType.getSimpleName());
+    }
+
+    String paramString = Joiner.on(", ").join(paramStrings);
+    return "#" + method.getName() + "(" + paramString + ")";
+  }
+
+  /**
+   * Eliminates runs of lowercase characters and numbers separated by periods.
+   * Seems to remove packages from fully-qualified type names pretty well.
+   */
+  private String stripPackages(String str) {
+    return str.replaceAll("(^|[< .\\(])([a-z0-9]+\\.)*", "$1");
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java b/extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java
new file mode 100644
index 0000000..c2da39f
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.spi.ConstructorBinding;
+import com.google.inject.spi.ConvertedConstantBinding;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.LinkedKeyBinding;
+import com.google.inject.spi.ProviderBinding;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderKeyBinding;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * {@link com.google.inject.spi.BindingTargetVisitor} that returns a
+ * {@link Collection} of the {@link Key}s of each {@link Binding}'s
+ * dependencies. Used by {@link InjectorGrapher} to walk the dependency graph
+ * from a starting set of {@link Binding}s.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class TransitiveDependencyVisitor
+    extends DefaultBindingTargetVisitor<Object, Collection<Key<?>>> {
+
+  private Collection<Key<?>> visitHasDependencies(HasDependencies hasDependencies) {
+    Set<Key<?>> dependencies = Sets.newHashSet();
+    
+    for (Dependency<?> dependency : hasDependencies.getDependencies()) {
+      dependencies.add(dependency.getKey());
+    }
+
+    return dependencies;
+  }
+  
+  @Override public Collection<Key<?>> visit(ConstructorBinding<?> binding) {
+    return visitHasDependencies(binding);
+  }
+
+  @Override public Collection<Key<?>> visit(ConvertedConstantBinding<?> binding) {
+    return visitHasDependencies(binding);
+  }
+
+  @Override public Collection<Key<?>> visit(InstanceBinding<?> binding) {
+    return visitHasDependencies(binding);
+  }
+
+  @Override public Collection<Key<?>> visit(LinkedKeyBinding<?> binding) {
+    return ImmutableSet.<Key<?>>of(binding.getLinkedKey());
+  }
+
+  @Override public Collection<Key<?>> visit(ProviderBinding<?> binding) {
+    return ImmutableSet.<Key<?>>of(binding.getProvidedKey());
+  }
+
+  @Override public Collection<Key<?>> visit(ProviderInstanceBinding<?> binding) {
+    return visitHasDependencies(binding);
+  }
+
+  @Override public Collection<Key<?>> visit(ProviderKeyBinding<?> binding) {
+    return ImmutableSet.<Key<?>>of(binding.getProviderKey());
+  }
+
+  /** @since 4.0 */
+  @Override public Collection<Key<?>> visitOther(Binding<?> binding) {
+    return ImmutableSet.of();
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/ArrowType.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/ArrowType.java
new file mode 100644
index 0000000..3f1d807
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/ArrowType.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+/**
+ * Arrow symbols that are available from Graphviz. These can be composed by
+ * concatenation to make double arrows and such.
+ * <p>
+ * See: http://www.graphviz.org/doc/info/arrows.html
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public enum ArrowType {
+  BOX("box"),
+  BOX_OPEN("obox"),
+  CROW("crow"),
+  DIAMOND("diamond"),
+  DIAMOND_OPEN("odiamond"),
+  DOT("dot"),
+  DOT_OPEN("odot"),
+  INVERTED("inv"),
+  INVERTED_OPEN("oinv"),
+  NONE("none"),
+  NORMAL("normal"),
+  NORMAL_OPEN("onormal"),
+  TEE("tee"),
+  VEE("vee");
+
+  private final String arrowType;
+
+  ArrowType(String arrowType) {
+    this.arrowType = arrowType;
+  }
+
+  @Override
+  public String toString() {
+    return arrowType;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/CompassPoint.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/CompassPoint.java
new file mode 100644
index 0000000..7e6945b
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/CompassPoint.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+/**
+ * Enum for the "compass point" values used to control where edge
+ * end points appear on the graph.
+ * <p>
+ * See: http://www.graphviz.org/doc/info/attrs.html#k:portPos
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public enum CompassPoint {
+  NORTH("n"),
+  NORTH_EAST("ne"),
+  EAST("e"),
+  SOUTH_EAST("se"),
+  SOUTH("s"),
+  SOUTH_WEST("sw"),
+  WEST("w"),
+  NORTH_WEST("nw"),
+  CENTER("c"),
+  EXTERIOR_SIDE("_");
+
+  /** Graphviz "compass_pt" value. */
+  private final String compassPt;
+
+  CompassPoint(String compassPt) {
+    this.compassPt = compassPt;
+  }
+
+  @Override
+  public String toString() {
+    return compassPt;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/EdgeStyle.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/EdgeStyle.java
new file mode 100644
index 0000000..121dbbf
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/EdgeStyle.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+/**
+ * Styles for edges.
+ * <p>
+ * See: http://www.graphviz.org/doc/info/attrs.html#k:style
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public enum EdgeStyle {
+  BOLD("bold"),
+  DASHED("dashed"),
+  DOTTED("dotted"),
+  INVISIBLE("invis"),
+  SOLID("solid");
+
+  private final String name;
+
+  EdgeStyle(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public String toString() {
+    return name;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/Graphviz.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/Graphviz.java
new file mode 100644
index 0000000..b86eadf
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/Graphviz.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher.graphviz;
+
+import com.google.inject.BindingAnnotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation for types used by the graphviz grapher.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ */
+@BindingAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@interface Graphviz {}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizEdge.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizEdge.java
new file mode 100644
index 0000000..0a8ff98
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizEdge.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.grapher.NodeId;
+
+import java.util.List;
+
+/**
+ * Data object to encapsulate the attributes of Graphviz edges that we're
+ * interested in drawing.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class GraphvizEdge {
+  private final NodeId headNodeId;
+  private String headPortId;
+  private CompassPoint headCompassPoint;
+  private List<ArrowType> arrowHead = ImmutableList.of(ArrowType.NORMAL);
+  
+  private final NodeId tailNodeId;
+  private String tailPortId;
+  private CompassPoint tailCompassPoint;
+  private List<ArrowType> arrowTail = ImmutableList.of(ArrowType.NONE);
+
+  private EdgeStyle style = EdgeStyle.SOLID;
+
+  public GraphvizEdge(NodeId tailNodeId, NodeId headNodeId) {
+    this.tailNodeId = tailNodeId;
+    this.headNodeId = headNodeId;
+  }
+
+  /** @since 4.0 */
+  public NodeId getHeadNodeId() {
+    return headNodeId;
+  }
+
+  public String getHeadPortId() {
+    return headPortId;
+  }
+
+  public void setHeadPortId(String headPortId) {
+    this.headPortId = headPortId;
+  }
+
+  public CompassPoint getHeadCompassPoint() {
+    return headCompassPoint;
+  }
+  
+  public void setHeadCompassPoint(CompassPoint headCompassPoint) {
+    this.headCompassPoint = headCompassPoint;
+  }
+
+  public List<ArrowType> getArrowHead() {
+    return arrowHead;
+  }
+
+  public void setArrowHead(List<ArrowType> arrowHead) {
+    this.arrowHead = ImmutableList.copyOf(arrowHead);
+  }
+
+  /** @since 4.0 */
+  public NodeId getTailNodeId() {
+    return tailNodeId;
+  }
+
+  public String getTailPortId() {
+    return tailPortId;
+  }
+
+  public void setTailPortId(String tailPortId) {
+    this.tailPortId = tailPortId;
+  }
+
+  public CompassPoint getTailCompassPoint() {
+    return tailCompassPoint;
+  }
+  
+  public void setTailCompassPoint(CompassPoint tailCompassPoint) {
+    this.tailCompassPoint = tailCompassPoint;
+  }
+
+  public List<ArrowType> getArrowTail() {
+    return arrowTail;
+  }
+
+  public void setArrowTail(List<ArrowType> arrowTail) {
+    this.arrowTail = ImmutableList.copyOf(arrowTail);
+  }
+
+  public EdgeStyle getStyle() {
+    return style;
+  }
+
+  public void setStyle(EdgeStyle style) {
+    this.style = style;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizGrapher.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizGrapher.java
new file mode 100644
index 0000000..71edd09
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizGrapher.java
@@ -0,0 +1,326 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.grapher.AbstractInjectorGrapher;
+import com.google.inject.grapher.BindingEdge;
+import com.google.inject.grapher.DependencyEdge;
+import com.google.inject.grapher.ImplementationNode;
+import com.google.inject.grapher.InstanceNode;
+import com.google.inject.grapher.InterfaceNode;
+import com.google.inject.grapher.NameFactory;
+import com.google.inject.grapher.NodeId;
+import com.google.inject.spi.InjectionPoint;
+import java.io.PrintWriter;
+import java.lang.reflect.Member;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * {@link com.google.inject.grapher.InjectorGrapher} implementation that writes out a Graphviz DOT
+ * file of the graph. Dependencies are bound in {@link GraphvizModule}.
+ * <p>
+ * Specify the {@link PrintWriter} to output to with {@link #setOut(PrintWriter)}.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ * @since 4.0
+ */
+public class GraphvizGrapher extends AbstractInjectorGrapher {
+  private final Map<NodeId, GraphvizNode> nodes = Maps.newHashMap();
+  private final List<GraphvizEdge> edges = Lists.newArrayList();
+  private final NameFactory nameFactory;
+  private final PortIdFactory portIdFactory;
+
+  private PrintWriter out;
+  private String rankdir = "TB";
+
+  @Inject GraphvizGrapher(@Graphviz NameFactory nameFactory,
+      @Graphviz PortIdFactory portIdFactory) {
+    this.nameFactory = nameFactory;
+    this.portIdFactory = portIdFactory;
+  }
+
+  @Override protected void reset() {
+    nodes.clear();
+    edges.clear();
+  }
+
+  public void setOut(PrintWriter out) {
+    this.out = out;
+  }
+
+  public void setRankdir(String rankdir) {
+    this.rankdir = rankdir;
+  }
+
+  @Override protected void postProcess() {
+    start();
+    
+    for (GraphvizNode node : nodes.values()) {
+      renderNode(node);
+    }
+
+    for (GraphvizEdge edge : edges) {
+      renderEdge(edge);
+    }
+    
+    finish();
+    
+    out.flush();
+  }
+
+  protected Map<String, String> getGraphAttributes() {
+    Map<String, String> attrs = Maps.newHashMap();
+    attrs.put("rankdir", rankdir);
+    return attrs;
+  }
+
+  protected void start() {
+    out.println("digraph injector {");
+    
+    Map<String, String> attrs = getGraphAttributes();
+    out.println("graph " + getAttrString(attrs) + ";");
+  }
+
+  protected void finish() {
+    out.println("}");
+  }
+
+  protected void renderNode(GraphvizNode node) {
+    Map<String, String> attrs = getNodeAttributes(node);
+    out.println(node.getIdentifier() + " " + getAttrString(attrs));
+  }
+  
+  protected Map<String, String> getNodeAttributes(GraphvizNode node) {
+    Map<String, String> attrs = Maps.newHashMap();
+
+    attrs.put("label", getNodeLabel(node));
+    // remove most of the margin because the table has internal padding
+    attrs.put("margin", "\"0.02,0\"");
+    attrs.put("shape", node.getShape().toString());
+    attrs.put("style", node.getStyle().toString());
+    
+    return attrs;
+  }
+
+  /**
+   * Creates the "label" for a node. This is a string of HTML that defines a
+   * table with a heading at the top and (in the case of
+   * {@link ImplementationNode}s) rows for each of the member fields.
+   */
+  protected String getNodeLabel(GraphvizNode node) {
+    String cellborder = node.getStyle() == NodeStyle.INVISIBLE ? "1" : "0";
+    
+    StringBuilder html = new StringBuilder();
+    html.append("<");
+    html.append("<table cellspacing=\"0\" cellpadding=\"5\" cellborder=\"");
+    html.append(cellborder).append("\" border=\"0\">");
+    
+    html.append("<tr>").append("<td align=\"left\" port=\"header\" ");
+    html.append("bgcolor=\"" + node.getHeaderBackgroundColor() + "\">");
+    
+    String subtitle = Joiner.on("<br align=\"left\"/>").join(node.getSubtitles());
+    if (subtitle.length() != 0) {
+      html.append("<font color=\"").append(node.getHeaderTextColor());
+      html.append("\" point-size=\"10\">");
+      html.append(subtitle).append("<br align=\"left\"/>").append("</font>");
+    }
+
+    html.append("<font color=\"" + node.getHeaderTextColor() + "\">");
+    html.append(htmlEscape(node.getTitle())).append("<br align=\"left\"/>");
+    html.append("</font>").append("</td>").append("</tr>");
+
+    for (Map.Entry<String, String> field : node.getFields().entrySet()) {
+      html.append("<tr>");
+      html.append("<td align=\"left\" port=\"").append(htmlEscape(field.getKey())).append("\">");
+      html.append(htmlEscape(field.getValue()));
+      html.append("</td>").append("</tr>");
+    }
+
+    html.append("</table>");
+    html.append(">");
+    return html.toString();
+  }
+
+  protected void renderEdge(GraphvizEdge edge) {
+    Map<String, String> attrs = getEdgeAttributes(edge);
+    
+    String tailId = getEdgeEndPoint(nodes.get(edge.getTailNodeId()).getIdentifier(),
+        edge.getTailPortId(), edge.getTailCompassPoint());
+
+    String headId = getEdgeEndPoint(nodes.get(edge.getHeadNodeId()).getIdentifier(),
+        edge.getHeadPortId(), edge.getHeadCompassPoint());
+    
+    out.println(tailId + " -> " + headId + " " + getAttrString(attrs));
+  }
+
+  protected Map<String, String> getEdgeAttributes(GraphvizEdge edge) {
+    Map<String, String> attrs = Maps.newHashMap();
+    
+    attrs.put("arrowhead", getArrowString(edge.getArrowHead()));
+    attrs.put("arrowtail", getArrowString(edge.getArrowTail()));
+    attrs.put("style", edge.getStyle().toString());
+    
+    return attrs;
+  }
+  
+  private String getAttrString(Map<String, String> attrs) {
+    List<String> attrList = Lists.newArrayList();
+    
+    for (Entry<String, String> attr : attrs.entrySet()) {
+      String value = attr.getValue();
+
+      if (value != null) {
+        attrList.add(attr.getKey() + "=" + value);
+      }
+    }
+    
+    return "[" + Joiner.on(", ").join(attrList) + "]";
+  }
+
+  /**
+   * Turns a {@link List} of {@link ArrowType}s into a {@link String} that
+   * represents combining them. With Graphviz, that just means concatenating
+   * them.
+   */
+  protected String getArrowString(List<ArrowType> arrows) {
+    return Joiner.on("").join(arrows);
+  }
+
+  protected String getEdgeEndPoint(String nodeId, String portId, CompassPoint compassPoint) {
+    List<String> portStrings = Lists.newArrayList(nodeId);
+    
+    if (portId != null) {
+      portStrings.add(portId);
+    }
+    
+    if (compassPoint != null) {
+      portStrings.add(compassPoint.toString());
+    }
+    
+    return Joiner.on(":").join(portStrings);
+  }
+
+  protected String htmlEscape(String str) {
+    return str.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
+  }
+
+  protected List<String> htmlEscape(List<String> elements) {
+    List<String> escaped = Lists.newArrayList();
+    for (String element : elements) {
+      escaped.add(htmlEscape(element));
+    }
+    return escaped;
+  }
+
+  @Override protected void newInterfaceNode(InterfaceNode node) {
+    // TODO(phopkins): Show the Module on the graph, which comes from the
+    // class name when source is a StackTraceElement.
+
+    NodeId nodeId = node.getId();
+    GraphvizNode gnode = new GraphvizNode(nodeId);
+    gnode.setStyle(NodeStyle.DASHED);
+    Key<?> key = nodeId.getKey();
+    gnode.setTitle(nameFactory.getClassName(key));
+    gnode.addSubtitle(0, nameFactory.getAnnotationName(key));
+    addNode(gnode);
+  }
+
+  @Override protected void newImplementationNode(ImplementationNode node) {
+    NodeId nodeId = node.getId();
+    GraphvizNode gnode = new GraphvizNode(nodeId);
+    gnode.setStyle(NodeStyle.SOLID);
+
+    gnode.setHeaderBackgroundColor("#000000");
+    gnode.setHeaderTextColor("#ffffff");
+    gnode.setTitle(nameFactory.getClassName(nodeId.getKey()));
+
+    for (Member member : node.getMembers()) {
+      gnode.addField(portIdFactory.getPortId(member), nameFactory.getMemberName(member));
+    }
+
+    addNode(gnode);
+  }
+
+  @Override protected void newInstanceNode(InstanceNode node) {
+    NodeId nodeId = node.getId();
+    GraphvizNode gnode = new GraphvizNode(nodeId);
+    gnode.setStyle(NodeStyle.SOLID);
+
+    gnode.setHeaderBackgroundColor("#000000");
+    gnode.setHeaderTextColor("#ffffff");
+    gnode.setTitle(nameFactory.getClassName(nodeId.getKey()));
+
+    gnode.addSubtitle(0, nameFactory.getSourceName(node.getSource()));
+
+    gnode.setHeaderBackgroundColor("#aaaaaa");
+    gnode.setHeaderTextColor("#ffffff");
+    gnode.setTitle(nameFactory.getInstanceName(node.getInstance()));
+
+    for (Member member : node.getMembers()) {
+      gnode.addField(portIdFactory.getPortId(member), nameFactory.getMemberName(member));
+    }
+
+    addNode(gnode);
+  }
+
+  @Override protected void newDependencyEdge(DependencyEdge edge) {
+    GraphvizEdge gedge = new GraphvizEdge(edge.getFromId(), edge.getToId());
+    InjectionPoint fromPoint = edge.getInjectionPoint();
+    if (fromPoint == null) {
+      gedge.setTailPortId("header");
+    } else {
+      gedge.setTailPortId(portIdFactory.getPortId(fromPoint.getMember()));
+    }
+    gedge.setArrowHead(ImmutableList.of(ArrowType.NORMAL));
+    gedge.setTailCompassPoint(CompassPoint.EAST);
+
+    edges.add(gedge);
+  }
+
+  @Override protected void newBindingEdge(BindingEdge edge) {
+    GraphvizEdge gedge = new GraphvizEdge(edge.getFromId(), edge.getToId());
+    gedge.setStyle(EdgeStyle.DASHED);
+    switch (edge.getType()) {
+      case NORMAL:
+        gedge.setArrowHead(ImmutableList.of(ArrowType.NORMAL_OPEN));
+        break;
+
+      case PROVIDER:
+        gedge.setArrowHead(ImmutableList.of(ArrowType.NORMAL_OPEN, ArrowType.NORMAL_OPEN));
+        break;
+
+      case CONVERTED_CONSTANT:
+        gedge.setArrowHead(ImmutableList.of(ArrowType.NORMAL_OPEN, ArrowType.DOT_OPEN));
+        break;
+    }
+
+    edges.add(gedge);
+  }
+
+  private void addNode(GraphvizNode node) {
+    node.setIdentifier("x" + nodes.size());
+    nodes.put(node.getNodeId(), node);
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizModule.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizModule.java
new file mode 100644
index 0000000..db7f3f3
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizModule.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.grapher.NameFactory;
+import com.google.inject.grapher.ShortNameFactory;
+
+/**
+ * Module that provides classes needed by {@link GraphvizGrapher}.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class GraphvizModule extends AbstractModule {
+  @Override protected void configure() {
+    bind(NameFactory.class)
+        .annotatedWith(Graphviz.class)
+        .to(ShortNameFactory.class);
+    bind(PortIdFactory.class)
+        .annotatedWith(Graphviz.class)
+        .to(PortIdFactoryImpl.class);
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizNode.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizNode.java
new file mode 100644
index 0000000..37a1f79
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizNode.java
@@ -0,0 +1,125 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.inject.grapher.NodeId;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Data object to encapsulate the attributes of Graphviz nodes that we're
+ * interested in drawing.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class GraphvizNode {
+  private final NodeId nodeId;
+
+  private NodeStyle style = NodeStyle.SOLID;
+  private NodeShape shape = NodeShape.BOX;
+  
+  private String title = "";
+  private Map<Integer, String> subtitles = Maps.newTreeMap();
+  
+  private String headerTextColor = "#000000";
+  private String headerBackgroundColor = "#ffffff";
+
+  private String identifier;
+
+  /** {@link Map} from port ID to field title */
+  private Map<String, String> fields = Maps.newLinkedHashMap();
+
+  /** @since 4.0 */
+  public GraphvizNode(NodeId nodeId) {
+    this.nodeId = nodeId;
+  }
+
+  /** @since 4.0 */
+  public NodeId getNodeId() {
+    return nodeId;
+  }
+
+  public NodeShape getShape() {
+    return shape;
+  }
+  
+  public void setShape(NodeShape shape) {
+    this.shape = shape;
+  }
+  
+  public NodeStyle getStyle() {
+    return style;
+  }
+
+  public void setStyle(NodeStyle style) {
+    this.style = style;
+  }
+
+  public String getTitle() {
+    return title;
+  }
+
+  public void setTitle(String title) {
+    this.title = title;
+  }
+
+  public List<String> getSubtitles() {
+    return ImmutableList.copyOf(subtitles.values());
+  }
+
+  public void addSubtitle(int position, String subtitle) {
+    this.subtitles.put(position, subtitle);
+  }
+
+  public String getHeaderTextColor() {
+    return headerTextColor;
+  }
+
+  public void setHeaderTextColor(String headerTextColor) {
+    this.headerTextColor = headerTextColor;
+  }
+
+  public String getHeaderBackgroundColor() {
+    return headerBackgroundColor;
+  }
+
+  public void setHeaderBackgroundColor(String headerBackgroundColor) {
+    this.headerBackgroundColor = headerBackgroundColor;
+  }
+
+  public void addField(String portId, String title) {
+    fields.put(portId, title);
+  }
+
+  public Map<String, String> getFields() {
+    return ImmutableMap.copyOf(fields);
+  }
+
+  /** @since 4.0 */
+  public String getIdentifier() {
+    return identifier;
+  }
+
+  /** @since 4.0 */
+  public void setIdentifier(String identifier) {
+    this.identifier = identifier;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/NodeShape.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/NodeShape.java
new file mode 100644
index 0000000..25e4286
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/NodeShape.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+/**
+ * Enum for the shapes that are most interesting for Guice graphing.
+ * <p>
+ * See: http://www.graphviz.org/doc/info/shapes.html
+ * 
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public enum NodeShape {
+  BOX("box"),
+  ELLIPSE("ellipse"),
+  NONE("none");
+  
+  private final String shape;
+  
+  NodeShape(String shape) {
+    this.shape = shape;
+  }
+
+  @Override
+  public String toString() {
+    return shape;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/NodeStyle.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/NodeStyle.java
new file mode 100644
index 0000000..bd9652d
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/NodeStyle.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+/**
+ * Styles for nodes. Similar to {@link EdgeStyle} but with a few more options.
+ * <p>
+ * See: http://www.graphviz.org/doc/info/attrs.html#k:style
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public enum NodeStyle {
+  BOLD("bold"),
+  DASHED("dashed"),
+  DIAGONALS("diagonals"),
+  DOTTED("dotted"),
+  INVISIBLE("invis"),
+  FILLED("filled"),
+  ROUNDED("rounded"),
+  SOLID("solid");
+
+  private final String name;
+
+  NodeStyle(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public String toString() {
+    return name;
+  }
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/PortIdFactory.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/PortIdFactory.java
new file mode 100644
index 0000000..1883fc8
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/PortIdFactory.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+import java.lang.reflect.Member;
+
+/**
+ * Interface for a service that returns Graphviz port IDs, used for naming the
+ * rows in {@link com.google.inject.grapher.ImplementationNode}-displaying {@link GraphvizNode}s.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public interface PortIdFactory {
+  String getPortId(Member member);
+}
diff --git a/extensions/grapher/src/com/google/inject/grapher/graphviz/PortIdFactoryImpl.java b/extensions/grapher/src/com/google/inject/grapher/graphviz/PortIdFactoryImpl.java
new file mode 100644
index 0000000..71b30d6
--- /dev/null
+++ b/extensions/grapher/src/com/google/inject/grapher/graphviz/PortIdFactoryImpl.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 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.inject.grapher.graphviz;
+
+import java.lang.reflect.Member;
+
+/**
+ * Implementation of {@link PortIdFactory}. Bound in {@link GraphvizModule}.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class PortIdFactoryImpl implements PortIdFactory {
+  public String getPortId(Member member) {
+    return "m_" + Integer.toHexString(member.hashCode());
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/AbstractInjectorGrapherTest.java b/extensions/grapher/test/com/google/inject/grapher/AbstractInjectorGrapherTest.java
new file mode 100644
index 0000000..a8a35e3
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/AbstractInjectorGrapherTest.java
@@ -0,0 +1,184 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.spi.InjectionPoint;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Member;
+import java.util.Set;
+
+/**
+ * Test cases for {@link AbstractInjectorGrapher}. This indirectly tests most classes in this
+ * package.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ */
+
+public class AbstractInjectorGrapherTest extends TestCase {
+  private static final String TEST_STRING = "test";
+
+  private static class FakeGrapher extends AbstractInjectorGrapher {
+    final Set<Node> nodes = Sets.newHashSet();
+    final Set<Edge> edges = Sets.newHashSet();
+
+    @Override protected void reset() {
+      nodes.clear();
+      edges.clear();
+    }
+
+    @Override protected void newInterfaceNode(InterfaceNode node) {
+      assertFalse(nodes.contains(node));
+      nodes.add(node);
+    }
+
+    @Override protected void newImplementationNode(ImplementationNode node) {
+      assertFalse(nodes.contains(node));
+      nodes.add(node);
+    }
+
+    @Override protected void newInstanceNode(InstanceNode node) {
+      assertFalse(nodes.contains(node));
+      nodes.add(node);
+    }
+
+    @Override protected void newDependencyEdge(DependencyEdge edge) {
+      assertFalse(edges.contains(edge));
+      edges.add(edge);
+    }
+
+    @Override protected void newBindingEdge(BindingEdge edge) {
+      assertFalse(edges.contains(edge));
+      edges.add(edge);
+    }
+
+    @Override protected void postProcess() {}
+  }
+
+  private static final class Wrapper<T> {
+    T value;
+  }
+
+  @BindingAnnotation
+  @Retention(RetentionPolicy.RUNTIME)
+  private static @interface Ann {}
+  private static interface IA {}
+  private static class A implements IA {
+    @Inject public A(String str) {}
+  }
+  private static class A2 implements IA {
+    @Inject public A2(Provider<String> strProvider) {}
+  }
+
+  private Node aNode;
+  private Node a2Node;
+  private Node iaNode;
+  private Node iaAnnNode;
+  private Node stringNode;
+  private Node stringInstanceNode;
+
+  private FakeGrapher grapher;
+
+  @Override protected void setUp() throws Exception {
+    super.setUp();
+    grapher = new FakeGrapher();
+    Node.ignoreSourceInComparisons = true;
+    aNode = new ImplementationNode(NodeId.newTypeId(Key.get(A.class)), null,
+        ImmutableList.<Member>of(A.class.getConstructor(String.class)));
+    a2Node = new ImplementationNode(NodeId.newTypeId(Key.get(A2.class)), null,
+        ImmutableList.<Member>of(A2.class.getConstructor(Provider.class)));
+    iaNode = new InterfaceNode(NodeId.newTypeId(Key.get(IA.class)), null);
+    iaAnnNode = new InterfaceNode(NodeId.newTypeId(Key.get(IA.class, Ann.class)), null);
+    stringNode = new InterfaceNode(NodeId.newTypeId(Key.get(String.class)), null);
+    stringInstanceNode = new InstanceNode(NodeId.newInstanceId(Key.get(String.class)), null,
+        TEST_STRING, ImmutableList.<Member>of());
+  }
+
+  public void testLinkedAndInstanceBindings() throws Exception {
+    grapher.graph(Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(IA.class).to(A.class);
+          bind(IA.class).annotatedWith(Ann.class).to(A.class);
+          bind(String.class).toInstance(TEST_STRING);
+        }
+    }));
+
+    Set<Node> expectedNodes =
+        ImmutableSet.<Node>of(iaNode, iaAnnNode, aNode, stringNode, stringInstanceNode);
+    Set<Edge> expectedEdges = ImmutableSet.<Edge>of(
+        new BindingEdge(iaNode.getId(), aNode.getId(), BindingEdge.Type.NORMAL),
+        new BindingEdge(iaAnnNode.getId(), aNode.getId(), BindingEdge.Type.NORMAL),
+        new BindingEdge(stringNode.getId(), stringInstanceNode.getId(), BindingEdge.Type.NORMAL),
+        new DependencyEdge(aNode.getId(), stringNode.getId(),
+            InjectionPoint.forConstructor(A.class.getConstructor(String.class))));
+    assertEquals(expectedNodes, grapher.nodes);
+    assertEquals(expectedEdges, grapher.edges);
+  }
+
+  public void testProviderBindings() throws Exception {
+    final Wrapper<Provider<A2>> wrapper = new Wrapper<Provider<A2>>();
+    grapher.graph(Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          wrapper.value = getProvider(A2.class);
+          bind(IA.class).toProvider(wrapper.value);
+          bind(A2.class);
+          bind(String.class).toInstance(TEST_STRING);
+        }
+    }));
+
+    Node a2ProviderNode = new InstanceNode(NodeId.newInstanceId(Key.get(IA.class)), null,
+        wrapper.value, ImmutableList.<Member>of());
+    Set<Node> expectedNodes =
+        ImmutableSet.<Node>of(iaNode, stringNode, a2Node, stringInstanceNode, a2ProviderNode);
+    Set<Edge> expectedEdges = ImmutableSet.<Edge>of(
+        new BindingEdge(stringNode.getId(), stringInstanceNode.getId(), BindingEdge.Type.NORMAL),
+        new BindingEdge(iaNode.getId(), a2ProviderNode.getId(), BindingEdge.Type.PROVIDER),
+        new DependencyEdge(a2Node.getId(), stringNode.getId(),
+            InjectionPoint.forConstructor(A2.class.getConstructor(Provider.class))),
+        new DependencyEdge(a2ProviderNode.getId(), a2Node.getId(), null));
+    assertEquals("wrong nodes", expectedNodes, grapher.nodes);
+    assertEquals("wrong edges", expectedEdges, grapher.edges);
+  }
+
+  public void testGraphWithGivenRoot() throws Exception {
+    grapher.graph(Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          bind(IA.class).to(A.class);
+          bind(IA.class).annotatedWith(Ann.class).to(A.class);
+          bind(String.class).toInstance(TEST_STRING);
+        }
+    }), ImmutableSet.<Key<?>>of(Key.get(String.class)));
+
+    Set<Node> expectedNodes = ImmutableSet.<Node>of(stringNode, stringInstanceNode);
+    Set<Edge> expectedEdges = ImmutableSet.<Edge>of(
+        new BindingEdge(stringNode.getId(), stringInstanceNode.getId(), BindingEdge.Type.NORMAL));
+    assertEquals(expectedNodes, grapher.nodes);
+    assertEquals(expectedEdges, grapher.edges);
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/AllTests.java b/extensions/grapher/test/com/google/inject/grapher/AllTests.java
new file mode 100644
index 0000000..af81398
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/AllTests.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class AllTests {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+    suite.addTestSuite(AbstractInjectorGrapherTest.class);
+    suite.addTestSuite(ShortNameFactoryTest.class);
+    suite.addTestSuite(TransitiveDependencyVisitorTest.class);
+    return suite;
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/ShortNameFactoryTest.java b/extensions/grapher/test/com/google/inject/grapher/ShortNameFactoryTest.java
new file mode 100644
index 0000000..867a5a8
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/ShortNameFactoryTest.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.ProviderMethod;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.name.Names;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.ProviderInstanceBinding;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.reflect.Member;
+
+/**
+ * Tests for {@link ShortNameFactory}.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class ShortNameFactoryTest extends TestCase {
+  // Helper objects are up here because their line numbers are tested below.
+  private static class Obj {
+    @Annotated
+    public String field;
+    Obj() {}
+    void method(String parameter) {}
+  }
+
+  private static class ToStringObj {
+    @Override
+    public String toString() {
+      return "I'm a ToStringObj";
+    }
+  }
+  
+  @Retention(RUNTIME)
+  @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+  @BindingAnnotation
+  private @interface Annotated {}
+
+  private NameFactory nameFactory;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+
+    nameFactory = new ShortNameFactory();
+  }
+
+  public void testGetMemberName_field() throws Exception {
+    Member field = Obj.class.getDeclaredField("field");
+    assertEquals("field", nameFactory.getMemberName(field));
+  }
+
+  public void testGetMemberName_method() throws Exception {
+    Member method = Obj.class.getDeclaredMethod("method", String.class);
+    assertEquals("#method(...)", nameFactory.getMemberName(method));
+  }
+
+  public void testGetMemberName_constructor() throws Exception {
+    Member constructor = Obj.class.getDeclaredConstructor();
+    assertEquals("<init>", nameFactory.getMemberName(constructor));
+  }
+
+  public void testGetAnnotationName_annotationType() throws Exception {
+    Key<?> key = Key.get(String.class, Annotated.class);
+    assertEquals("@Annotated", nameFactory.getAnnotationName(key));
+  }
+
+  public void testGetAnnotationName_annotationInstance() throws Exception {
+    Key<?> key = Key.get(String.class,
+        Obj.class.getDeclaredField("field").getDeclaredAnnotations()[0]);
+    assertEquals("@Annotated", nameFactory.getAnnotationName(key));
+  }
+
+  public void testGetAnnotationName_annotationInstanceWithParameters() throws Exception {
+    Key<?> key = Key.get(String.class, Names.named("name"));
+    assertEquals("@Named(value=name)", nameFactory.getAnnotationName(key));
+  }
+
+  public void testGetClassName_key() throws Exception {
+    Key<?> key = Key.get(Obj.class);
+    assertEquals("Class name should not have the package",
+        "ShortNameFactoryTest$Obj", nameFactory.getClassName(key));
+  }
+  
+  public void testGetClassName_keyWithTypeParameters() throws Exception {
+    Key<?> key = Key.get(new TypeLiteral<Provider<String>>() {});
+    assertEquals("Class name and type values should not have packages",
+        "Provider<String>", nameFactory.getClassName(key));
+  }
+
+  /**
+   * Tests the case where a provider method is the source of the 
+   * @throws Exception
+   */
+  public void testGetSourceName_method() throws Exception {
+    Member method = Obj.class.getDeclaredMethod("method", String.class);
+    assertEquals("Method should be identified by its file name and line number",
+        "ShortNameFactoryTest.java:53", nameFactory.getSourceName(method));
+  }
+
+  public void testGetSourceName_stackTraceElement() throws Exception {
+    StackTraceElement element = 
+        (StackTraceElement) StackTraceElements.forMember(Obj.class.getField("field"));
+    assertEquals("Stack trace element should be identified by its file name and line number",
+        "ShortNameFactoryTest.java:52", nameFactory.getSourceName(element));
+  }
+
+  public void testGetInstanceName_defaultToString() throws Exception {
+    assertEquals("Should use class name instead of Object#toString()",
+        "ShortNameFactoryTest$Obj", nameFactory.getInstanceName(new Obj()));
+  }
+  
+  public void testGetInstanceName_customToString() throws Exception {
+    assertEquals("Should use class's toString() method since it's defined",
+        "I'm a ToStringObj", nameFactory.getInstanceName(new ToStringObj()));
+  }
+  
+  public void testGetInstanceName_string() throws Exception {
+    assertEquals("String should have quotes to evoke a string literal",
+        "\"My String Instance\"", nameFactory.getInstanceName("My String Instance"));
+  }
+  
+  public void testGetInstanceName_providerMethod() throws Exception {
+    final ProviderMethod<?>[] methodHolder = new ProviderMethod[1];
+    
+    Injector injector = Guice.createInjector(new ProvidingModule());
+    injector.getBinding(Integer.class).acceptTargetVisitor(
+        new DefaultBindingTargetVisitor<Object, Void>() {
+          @SuppressWarnings("unchecked") @Override
+          public Void visit(ProviderInstanceBinding<?> binding) {
+            methodHolder[0] = (ProviderMethod) binding.getUserSuppliedProvider();
+            return null;
+          }
+        });
+    
+    assertEquals("Method provider should pretty print as the method signature",
+        "#provideInteger(String)", nameFactory.getInstanceName(methodHolder[0]));
+  }
+  
+  private static class ProvidingModule extends AbstractModule {
+    @Override
+    protected void configure() {}
+    
+    @Provides
+    public Integer provideInteger(String string) {
+      return Integer.valueOf(string);
+    }
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java b/extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java
new file mode 100644
index 0000000..23ebbc0
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java
@@ -0,0 +1,220 @@
+/**
+ * Copyright (C) 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.inject.grapher;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+import com.google.inject.spi.ConstructorBinding;
+import com.google.inject.spi.ConvertedConstantBinding;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.LinkedKeyBinding;
+import com.google.inject.spi.ProviderBinding;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderKeyBinding;
+
+import junit.framework.TestCase;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Tests for {@link TransitiveDependencyVisitor}.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class TransitiveDependencyVisitorTest extends TestCase {
+  private TransitiveDependencyVisitor visitor;
+  
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    
+    visitor = new TransitiveDependencyVisitor();
+  }
+
+  public void testVisitConstructor() {
+    Binding<?> binding = getBinding(Key.get(ConstructedClass.class));
+    Collection<Key<?>> dependencies = visitor.visit((ConstructorBinding<?>) binding);
+    
+    assertDependencies(dependencies, Key.get(A.class), Key.get(B.class), Key.get(C.class),
+        Key.get(D.class));
+  }
+
+  public void testVisitConvertedConstant() {
+    Binding<?> binding = getBinding(Key.get(Integer.class, Names.named("number")),
+        new ConvertedConstantModule());
+    Collection<Key<?>> dependencies = visitor.visit(
+        (ConvertedConstantBinding<?>) binding);
+    
+    assertDependencies(dependencies, Key.get(String.class, Names.named("number")));
+  }
+
+  public void testVisitInstance() {
+    Binding<?> binding = getBinding(Key.get(ConstructedClass.class), new InstanceModule());
+    Collection<Key<?>> dependencies = visitor.visit(
+        (InstanceBinding<?>) binding);
+    
+    // Dependencies will only be on the field- and method-injected classes.
+    assertDependencies(dependencies, Key.get(A.class), Key.get(D.class));
+  }
+
+  public void testVisitInstance_instanceHasDependencies() {
+    Binding<?> binding = getBinding(Key.get(Interface.class), new HasDependenciesModule());
+    Collection<Key<?>> dependencies = visitor.visit(
+        (InstanceBinding<?>) binding);
+    
+    // Dependencies should only be on the stated
+    // HasDependencies#getDependencies() values
+    assertDependencies(dependencies, Key.get(G.class));
+  }
+
+  public void testVisitLinkedKey() {
+    Binding<?> binding = getBinding(Key.get(Interface.class), new LinkedKeyModule());
+    Collection<Key<?>> dependencies = visitor.visit((LinkedKeyBinding<?>) binding);
+
+    // Dependency should be to the class this interface is bound to.
+    assertDependencies(dependencies, Key.get(ConstructedClass.class));
+  }
+
+  public void testVisitProviderBinding() {
+    Binding<?> binding = getBinding(Key.get(new TypeLiteral<Provider<ConstructedClass>>() {}));
+    Collection<Key<?>> dependencies = visitor.visit((ProviderBinding<?>) binding);
+    
+    assertDependencies(dependencies, Key.get(ConstructedClass.class));
+  }
+
+  public void testVisitProviderInstance() {
+    Binding<?> binding = getBinding(Key.get(ConstructedClass.class),
+        new ProviderInstanceModule());
+    Collection<Key<?>> dependencies = visitor.visit(
+        (ProviderInstanceBinding<?>) binding);
+    
+    // Dependencies will only be on the field- and method-injected classes.
+    assertDependencies(dependencies, Key.get(E.class), Key.get(F.class));
+  }
+
+  public void testVisitProviderKey() {
+    Binding<?> binding = getBinding(Key.get(ConstructedClass.class), new ProviderKeyModule());
+    Collection<Key<?>> dependencies = visitor.visit((ProviderKeyBinding<?>) binding);
+
+    // Dependency should be to the class that provides this one.
+    assertDependencies(dependencies, Key.get(ConstructedClassProvider.class));
+  }
+  
+  private Binding<?> getBinding(Key<?> key, Module... modules) {
+    return Guice.createInjector(modules).getBinding(key);
+  }
+  
+  private void assertDependencies(Collection<Key<?>> dependencies, Key<?>... keys) {
+    assertNotNull("Dependencies should not be null", dependencies);
+    assertEquals("There should be " + keys.length + " dependencies",
+        keys.length, dependencies.size());
+
+    for (Key<?> key : keys) {
+      assertTrue("Dependencies should contain " + key, dependencies.contains(key));
+    }
+  }
+
+  private static class A {}
+  private static class B {}
+  private static class C {}
+  private static class D {}
+  private static class E {}
+  private static class F {}
+  private static class G {}
+  
+  private static interface Interface {}
+  
+  private static class ConstructedClass implements Interface {
+    @Inject A a;
+    ConstructedClass() {}
+    @Inject ConstructedClass(B b, C c) {}
+    @Inject void setD(D d) {}
+  }
+
+  private static class ConstructedClassProvider implements Provider<ConstructedClass> {
+    @Inject E e;
+    ConstructedClassProvider() {}
+    @Inject ConstructedClassProvider(A a, B b, C c) {}
+    @Inject void setF(F f) {}
+    
+    public ConstructedClass get() {
+      return null;
+    }
+  }
+
+  private static class HasDependenciesClass implements Interface, HasDependencies {
+    @Inject A a;
+    @Inject B b;
+    
+    public Set<Dependency<?>> getDependencies() {
+      return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(G.class)));
+    }
+  }
+
+  private static class ConvertedConstantModule extends AbstractModule {
+    @Override
+    protected void configure() {
+      bindConstant().annotatedWith(Names.named("number")).to("2008");
+    }
+  }
+
+  private static class InstanceModule extends AbstractModule {
+    @Override
+    protected void configure() {
+      bind(ConstructedClass.class).toInstance(new ConstructedClass());
+    }
+  }
+
+  private static class LinkedKeyModule extends AbstractModule {
+    @Override
+    protected void configure() {
+      bind(Interface.class).to(ConstructedClass.class);
+    }
+  }
+  
+  private static class ProviderInstanceModule extends AbstractModule {
+    @Override
+    protected void configure() {
+      bind(ConstructedClass.class).toProvider(new ConstructedClassProvider());
+    }
+  }
+
+  private static class HasDependenciesModule extends AbstractModule {
+    @Override
+    protected void configure() {
+      bind(Interface.class).toInstance(new HasDependenciesClass());
+    }
+  }
+  
+  private static class ProviderKeyModule extends AbstractModule {
+    @Override
+    protected void configure() {
+      bind(ConstructedClass.class).toProvider(ConstructedClassProvider.class);
+    }
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/AssistedInjectModule.java b/extensions/grapher/test/com/google/inject/grapher/demo/AssistedInjectModule.java
new file mode 100644
index 0000000..95a83c1
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/AssistedInjectModule.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+
+/**
+ * Module to add {@link AssistedInject}-based elements to the demo
+ * {@link Injector}.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class AssistedInjectModule extends AbstractModule {
+  @Override
+  protected void configure() {
+    install(new FactoryModuleBuilder()
+        .implement(DanceParty.class, DancePartyImpl.class)
+        .build(DancePartyFactory.class));
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/BackToTheFutureModule.java b/extensions/grapher/test/com/google/inject/grapher/demo/BackToTheFutureModule.java
new file mode 100644
index 0000000..f594169
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/BackToTheFutureModule.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+
+/**
+ * Module that adds a variety of different kinds of {@link Bindings} to be used
+ * to generate a comprehensive sample graph.
+ * 
+ * @see InjectorGrapherDemo
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class BackToTheFutureModule extends AbstractModule {
+  @Override
+  protected void configure() {
+    bind(DeLorian.class);
+
+    bind(EnergySource.class).annotatedWith(Nuclear.class).to(Plutonium.class);
+    bind(EnergySource.class).annotatedWith(Renewable.class).to(Lightning.class);
+
+    bind(Plutonium.class).toProvider(PlutoniumProvider.class);
+    bind(PinballParts.class).annotatedWith(Used.class).toInstance(new PinballParts());
+
+    bind(Person.class).annotatedWith(Driver.class).to(MartyMcFly.class).in(Singleton.class);
+    bind(Person.class).annotatedWith(Inventor.class).to(DocBrown.class).in(Singleton.class);
+    
+    bindConstant().annotatedWith(Names.named("year")).to("1955");
+  }
+  
+  @Provides
+  public FluxCapacitor provideFluxCapacitor(EnergySource energySource) {
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/DanceParty.java b/extensions/grapher/test/com/google/inject/grapher/demo/DanceParty.java
new file mode 100644
index 0000000..930cd5f
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/DanceParty.java
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+interface DanceParty {}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/DancePartyFactory.java b/extensions/grapher/test/com/google/inject/grapher/demo/DancePartyFactory.java
new file mode 100644
index 0000000..b131566
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/DancePartyFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+/**
+ * Interface to be used with {@link FactoryProvider}.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+interface DancePartyFactory {
+  DanceParty newDanceParty(String thatNewSound);
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/DancePartyImpl.java b/extensions/grapher/test/com/google/inject/grapher/demo/DancePartyImpl.java
new file mode 100644
index 0000000..14185ec
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/DancePartyImpl.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+class DancePartyImpl implements DanceParty {
+  @Inject
+  public DancePartyImpl(@Assisted String thatNewSound, MartyMcFly guitarist) {}
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/DeLorian.java b/extensions/grapher/test/com/google/inject/grapher/demo/DeLorian.java
new file mode 100644
index 0000000..cf3537e
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/DeLorian.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+class DeLorian {
+  // We @Inject a Provider to demonstrate that the graph doesn't differentiate
+  // between a Provider<T> and just @Injecting T. 
+  @Inject @Driver Provider<Person> driver;
+  @Inject FluxCapacitor fluxCapacitor;
+  @Inject PrivateTestModule.Exposed exposed;
+  
+  @Inject
+  public void setEnergySource(EnergySource energySource) {}
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/DocBrown.java b/extensions/grapher/test/com/google/inject/grapher/demo/DocBrown.java
new file mode 100644
index 0000000..31c9678
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/DocBrown.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.Inject;
+
+class DocBrown implements Person {
+  // handy because it introduces a cycle
+  @Inject DeLorian stylishCar;
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/Driver.java b/extensions/grapher/test/com/google/inject/grapher/demo/Driver.java
new file mode 100644
index 0000000..1187c68
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/Driver.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@BindingAnnotation
+@interface Driver {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/EnergySource.java b/extensions/grapher/test/com/google/inject/grapher/demo/EnergySource.java
new file mode 100644
index 0000000..47c1f01
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/EnergySource.java
@@ -0,0 +1,22 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.ProvidedBy;
+
+@ProvidedBy(EnergySourceProvider.class)
+interface EnergySource {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/EnergySourceProvider.java b/extensions/grapher/test/com/google/inject/grapher/demo/EnergySourceProvider.java
new file mode 100644
index 0000000..7e8f3ca
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/EnergySourceProvider.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.name.Named;
+
+class EnergySourceProvider implements Provider<EnergySource> {
+  @Inject void setSources(@Nuclear EnergySource nuclear, @Renewable EnergySource renewable) {}
+  
+  // This will demonstrate a ConvertedConstantBinding.
+  @Inject void setYear(@Named("year") int year) {}
+  
+  public EnergySource get() {
+    return null;
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/FluxCapacitor.java b/extensions/grapher/test/com/google/inject/grapher/demo/FluxCapacitor.java
new file mode 100644
index 0000000..8dce4cd
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/FluxCapacitor.java
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+class FluxCapacitor {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/InjectorGrapherDemo.java b/extensions/grapher/test/com/google/inject/grapher/demo/InjectorGrapherDemo.java
new file mode 100644
index 0000000..1e36dd5
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/InjectorGrapherDemo.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.google.inject.grapher.graphviz.GraphvizGrapher;
+import com.google.inject.grapher.graphviz.GraphvizModule;
+
+import java.io.File;
+import java.io.PrintWriter;
+
+/**
+ * Application that instantiates {@link BackToTheFutureModule} and graphs it,
+ * writing the output to a DOT-formatted file (filename specified on the
+ * command line).
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class InjectorGrapherDemo {
+  public static void main(String[] args) throws Exception {
+    // TODO(phopkins): Switch to Stage.TOOL when issue 297 is fixed.
+    Injector demoInjector = Guice.createInjector(Stage.DEVELOPMENT,
+        new BackToTheFutureModule(), new MultibinderModule(), new PrivateTestModule());
+    PrintWriter out = new PrintWriter(new File(args[0]), "UTF-8");
+
+    Injector injector = Guice.createInjector(new GraphvizModule());
+    GraphvizGrapher grapher = injector.getInstance(GraphvizGrapher.class);
+    grapher.setOut(out);
+    grapher.setRankdir("TB");
+    grapher.graph(demoInjector);
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/Inventor.java b/extensions/grapher/test/com/google/inject/grapher/demo/Inventor.java
new file mode 100644
index 0000000..f9c8ab8
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/Inventor.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@BindingAnnotation
+@interface Inventor {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/Lightning.java b/extensions/grapher/test/com/google/inject/grapher/demo/Lightning.java
new file mode 100644
index 0000000..6df5539
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/Lightning.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+class Lightning implements EnergySource {
+  @Inject @Named("year") String yearOfStrike;
+}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/MartyMcFly.java b/extensions/grapher/test/com/google/inject/grapher/demo/MartyMcFly.java
new file mode 100644
index 0000000..96a8510
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/MartyMcFly.java
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+class MartyMcFly implements Person {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/MultibinderModule.java b/extensions/grapher/test/com/google/inject/grapher/demo/MultibinderModule.java
new file mode 100644
index 0000000..bf8f7ec
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/MultibinderModule.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+
+/**
+ * Module to add {@link Multibinder}-based bindings to the injector.
+ *
+ * @author phopkins@gmail.com (Pete Hopkins)
+ */
+public class MultibinderModule extends AbstractModule {
+  @Override
+  protected void configure() {
+    Multibinder<Person> charactersBinder = Multibinder.newSetBinder(binder(), Person.class);
+    charactersBinder.addBinding().to(MartyMcFly.class);
+    charactersBinder.addBinding().to(DocBrown.class);
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/Nuclear.java b/extensions/grapher/test/com/google/inject/grapher/demo/Nuclear.java
new file mode 100644
index 0000000..e273dd6
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/Nuclear.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@BindingAnnotation
+@interface Nuclear {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/Person.java b/extensions/grapher/test/com/google/inject/grapher/demo/Person.java
new file mode 100644
index 0000000..60a38dc
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/Person.java
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+interface Person {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java b/extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java
new file mode 100644
index 0000000..9ad9745
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+class PinballParts {
+  // Shows up as an injection point on an instance. We use a Provider so that
+  // it doesn't have to be satisfied when the Injector is created.
+  @Inject Provider<DocBrown> salvager;
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/Plutonium.java b/extensions/grapher/test/com/google/inject/grapher/demo/Plutonium.java
new file mode 100644
index 0000000..6594324
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/Plutonium.java
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+class Plutonium implements EnergySource {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/PlutoniumProvider.java b/extensions/grapher/test/com/google/inject/grapher/demo/PlutoniumProvider.java
new file mode 100644
index 0000000..3b8600a
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/PlutoniumProvider.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+class PlutoniumProvider implements Provider<Plutonium> {
+  @Inject public PlutoniumProvider(@Inventor Person inventor, @Used PinballParts parts) {}
+
+  public Plutonium get() {
+    return null;
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/PrivateTestModule.java b/extensions/grapher/test/com/google/inject/grapher/demo/PrivateTestModule.java
new file mode 100644
index 0000000..7619897
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/PrivateTestModule.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.grapher.demo;
+
+import com.google.inject.PrivateModule;
+
+/**
+ * Module to test private modules and exposed bindings.
+ *
+ * @author bojand@google.com (Bojan Djordjevic)
+ */
+public class PrivateTestModule extends PrivateModule {
+  interface Exposed {}
+  static class Hidden implements Exposed {}
+
+  @Override protected void configure() {
+    bind(Exposed.class).to(Hidden.class);
+    expose(Exposed.class);
+  }
+}
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/Renewable.java b/extensions/grapher/test/com/google/inject/grapher/demo/Renewable.java
new file mode 100644
index 0000000..d97a78c
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/Renewable.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@BindingAnnotation
+@interface Renewable {}
\ No newline at end of file
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/Used.java b/extensions/grapher/test/com/google/inject/grapher/demo/Used.java
new file mode 100644
index 0000000..d103505
--- /dev/null
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/Used.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 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.inject.grapher.demo;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@BindingAnnotation
+@interface Used {}
\ No newline at end of file
diff --git a/extensions/jmx/.gitignore b/extensions/jmx/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/extensions/jmx/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/extensions/jmx/build.properties b/extensions/jmx/build.properties
new file mode 100644
index 0000000..5d1f8ba
--- /dev/null
+++ b/extensions/jmx/build.properties
@@ -0,0 +1,5 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+module=com.google.inject.tools.jmx
diff --git a/extensions/jmx/build.xml b/extensions/jmx/build.xml
new file mode 100644
index 0000000..aeb7da7
--- /dev/null
+++ b/extensions/jmx/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-jmx" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/jmx/pom.xml b/extensions/jmx/pom.xml
new file mode 100644
index 0000000..b7f9d90
--- /dev/null
+++ b/extensions/jmx/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-jmx</artifactId>
+
+  <name>Google Guice - Extensions - JMX</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <skip>true</skip> <!-- Test is not actually a unit test. -->
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBinding.java b/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBinding.java
new file mode 100644
index 0000000..798b8f9
--- /dev/null
+++ b/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBinding.java
@@ -0,0 +1,40 @@
+/**
+ * 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 com.google.inject.tools.jmx;
+
+import com.google.inject.Binding;
+
+class ManagedBinding implements ManagedBindingMBean {
+
+  final Binding binding;
+
+  ManagedBinding(Binding binding) {
+    this.binding = binding;
+  }
+
+  public String getSource() {
+    return binding.getSource().toString();
+  }
+
+  public String getKey() {
+    return binding.getKey().toString();
+  }
+
+  public String getProvider() {
+    return binding.getProvider().toString();
+  }
+}
diff --git a/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBindingMBean.java b/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBindingMBean.java
new file mode 100644
index 0000000..6f9469a
--- /dev/null
+++ b/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBindingMBean.java
@@ -0,0 +1,40 @@
+/**
+ * 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 com.google.inject.tools.jmx;
+
+/**
+ * JMX interface to bindings.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public interface ManagedBindingMBean {
+
+  /**
+   * Gets the source of this binding.
+   */
+  String getSource();
+
+  /**
+   * Gets the provider to which this binding is bound.
+   */
+  String getProvider();
+
+  /**
+   * Gets the binding key.
+   */
+  String getKey();
+}
diff --git a/extensions/jmx/src/com/google/inject/tools/jmx/Manager.java b/extensions/jmx/src/com/google/inject/tools/jmx/Manager.java
new file mode 100644
index 0000000..03cbdb8
--- /dev/null
+++ b/extensions/jmx/src/com/google/inject/tools/jmx/Manager.java
@@ -0,0 +1,114 @@
+/**
+ * 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 com.google.inject.tools.jmx;
+
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+
+import java.lang.annotation.Annotation;
+import java.lang.management.ManagementFactory;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+/**
+ * Provides a JMX interface to Guice.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class Manager {
+
+  /**
+   * Registers all the bindings of an Injector with the platform MBean server.
+   * Consider using the name of your root {@link Module} class as the domain.
+   */
+  public static void manage(
+      String domain,
+      Injector injector) {
+    manage(ManagementFactory.getPlatformMBeanServer(), domain, injector);
+  }
+
+  /**
+   * Registers all the bindings of an Injector with the given MBean server.
+   * Consider using the name of your root {@link Module} class as the domain.
+   */
+  public static void manage(MBeanServer server, String domain,
+      Injector injector) {
+    // Register each binding independently.
+    for (Binding<?> binding : injector.getBindings().values()) {
+      // Construct the name manually so we can ensure proper ordering of the
+      // key/value pairs.
+      StringBuilder name = new StringBuilder();
+      name.append(domain).append(":");
+      Key<?> key = binding.getKey();
+      name.append("type=").append(quote(key.getTypeLiteral().toString()));
+      Annotation annotation = key.getAnnotation();
+      if (annotation != null) {
+        name.append(",annotation=").append(quote(annotation.toString()));
+      }
+      else {
+        Class<? extends Annotation> annotationType = key.getAnnotationType();
+        if (annotationType != null) {
+          name.append(",annotation=")
+              .append(quote("@" + annotationType.getName()));
+        }
+      }
+
+      try {
+        server.registerMBean(new ManagedBinding(binding),
+            new ObjectName(name.toString()));
+      }
+      catch (MalformedObjectNameException e) {
+        throw new RuntimeException("Bad object name: " + name, e);
+      }
+      catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+
+  static String quote(String value) {
+    // JMX seems to have a comma bug.
+    return ObjectName.quote(value).replace(',', ';');
+  }
+
+  /**
+   * Run with no arguments for usage instructions.
+   */
+  public static void main(String[] args) throws Exception {
+    if (args.length != 1) {
+      System.err.println("Usage: java -Dcom.sun.management.jmxremote "
+          + Manager.class.getName() + " [module class name]");
+      System.err.println("Then run 'jconsole' to connect.");
+      System.exit(1);
+    }
+
+    Module module = (Module) Class.forName(args[0]).newInstance();
+    Injector injector = Guice.createInjector(module);
+
+    manage(args[0], injector);
+
+    System.out.println("Press Ctrl+C to exit...");
+
+    // Sleep forever.
+    Thread.sleep(Long.MAX_VALUE);
+  }
+}
diff --git a/extensions/jmx/src/com/google/inject/tools/jmx/package-info.java b/extensions/jmx/src/com/google/inject/tools/jmx/package-info.java
new file mode 100644
index 0000000..e21f864
--- /dev/null
+++ b/extensions/jmx/src/com/google/inject/tools/jmx/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * JMX integration; this extension requires {@code guice-jmx.jar}.
+ */
+package com.google.inject.tools.jmx;
diff --git a/extensions/jmx/test/com/google/inject/tools/jmx/JmxTest.java b/extensions/jmx/test/com/google/inject/tools/jmx/JmxTest.java
new file mode 100644
index 0000000..bb10f95
--- /dev/null
+++ b/extensions/jmx/test/com/google/inject/tools/jmx/JmxTest.java
@@ -0,0 +1,63 @@
+/**
+ * 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 com.google.inject.tools.jmx;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+
+import java.lang.annotation.Retention;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class JmxTest {
+
+  interface Foo {}
+
+  static class FooImpl implements Foo {}
+
+  @Singleton
+  static class TransactionalFoo implements Foo {}
+
+  static class Bar {}
+
+  @BindingAnnotation @Retention(RUNTIME)
+  @interface Transactional {}
+
+  public static void main(String[] args) throws Exception {
+    Manager.main(new String[] { TestModule.class.getName() });
+  }
+  
+  public static class TestModule extends AbstractModule {
+
+    protected void configure() {
+      bind(Foo.class).to(FooImpl.class);
+      bind(Bar.class);
+      bind(Foo.class)
+          .annotatedWith(Transactional.class)
+          .to(FooImpl.class);
+      bindConstant().annotatedWith(Names.named("port")).to(8080);
+      bind(Key.get(Object.class)).to(Key.get(Bar.class));
+//      install(new ServletModule());
+    }
+  }
+}
diff --git a/extensions/jndi/build.properties b/extensions/jndi/build.properties
new file mode 100644
index 0000000..bc0b789
--- /dev/null
+++ b/extensions/jndi/build.properties
@@ -0,0 +1,5 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+module=com.google.inject.jndi
diff --git a/extensions/jndi/build.xml b/extensions/jndi/build.xml
new file mode 100644
index 0000000..780fceb
--- /dev/null
+++ b/extensions/jndi/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-jndi" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/jndi/pom.xml b/extensions/jndi/pom.xml
new file mode 100644
index 0000000..1eb2a18
--- /dev/null
+++ b/extensions/jndi/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-jndi</artifactId>
+
+  <name>Google Guice - Extensions - JNDI</name>
+
+</project>
diff --git a/extensions/jndi/src/com/google/inject/jndi/JndiIntegration.java b/extensions/jndi/src/com/google/inject/jndi/JndiIntegration.java
new file mode 100644
index 0000000..7907841
--- /dev/null
+++ b/extensions/jndi/src/com/google/inject/jndi/JndiIntegration.java
@@ -0,0 +1,67 @@
+/**
+ * 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 com.google.inject.jndi;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+/**
+ * Integrates Guice with JNDI. Requires a binding to 
+ * {@link javax.naming.Context}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class JndiIntegration {
+
+  private JndiIntegration() {}
+
+  /**
+   * Creates a provider which looks up objects in JNDI using the given name.
+   * Example usage:
+   *
+   * <pre>
+   * bind(DataSource.class).toProvider(fromJndi(DataSource.class, "java:..."));
+   * </pre>
+   */
+  public static <T> Provider<T> fromJndi(Class<T> type, String name) {
+    return new JndiProvider<T>(type, name);
+  }
+
+  static class JndiProvider<T> implements Provider<T> {
+
+    @Inject Context context;
+    final Class<T> type;
+    final String name;
+
+    public JndiProvider(Class<T> type, String name) {
+      this.type = type;
+      this.name = name;
+    }
+
+    public T get() {
+      try {
+        return type.cast(context.lookup(name));
+      }
+      catch (NamingException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+}
diff --git a/extensions/jndi/src/com/google/inject/jndi/package-info.java b/extensions/jndi/src/com/google/inject/jndi/package-info.java
new file mode 100644
index 0000000..f2f0af4
--- /dev/null
+++ b/extensions/jndi/src/com/google/inject/jndi/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * JNDI integration; this extension requires {@code guice-jndi.jar}.
+ */
+package com.google.inject.jndi;
diff --git a/extensions/mini/.gitignore b/extensions/mini/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/extensions/mini/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/extensions/mini/pom.xml b/extensions/mini/pom.xml
new file mode 100644
index 0000000..fdaa91d
--- /dev/null
+++ b/extensions/mini/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>guice-mini</artifactId>
+
+  <name>Google Guice - Extensions - Mini</name>
+
+</project>
diff --git a/extensions/mini/src/com/google/inject/mini/MiniGuice.java b/extensions/mini/src/com/google/inject/mini/MiniGuice.java
new file mode 100644
index 0000000..4dd242d
--- /dev/null
+++ b/extensions/mini/src/com/google/inject/mini/MiniGuice.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2010 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.inject.mini;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import javax.inject.Provider;
+
+/**
+ * Proof of concept. A tiny injector suitable for tiny applications.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @since 3.0
+ */
+public final class MiniGuice {
+  private static final Object UNINITIALIZED = new Object();
+  private MiniGuice() {}
+
+  private final Map<Key, Provider<?>> bindings = new HashMap<Key, Provider<?>>();
+  private final Queue<RequiredKey> requiredKeys = new ArrayDeque<RequiredKey>();
+  private final Set<Key> singletons = new HashSet<Key>();
+
+  /**
+   * Creates an injector defined by {@code modules} and immediately uses it to
+   * create an instance of {@code type}. The modules can be of any type, and
+   * must contain {@code @Provides} methods.
+   *
+   * <p>The following injection features are supported:
+   * <ul>
+   *   <li>Field injection. A class may have any number of field injections, and
+   *       fields may be of any visibility. Static fields will be injected each
+   *       time an instance is injected.
+   *   <li>Constructor injection. A class may have a single {@code
+   *       @Inject}-annotated constructor. Classes that have fields injected
+   *       may omit the {@link @Inject} annotation if they have a public
+   *       no-arguments constructor.
+   *   <li>Injection of {@code @Provides} method parameters.
+   *   <li>{@code @Provides} methods annotated {@code @Singleton}.
+   *   <li>Constructor-injected classes annotated {@code @Singleton}.
+   *   <li>Injection of {@link Provider}s.
+   *   <li>Binding annotations on injected parameters and fields.
+   *   <li>Guice annotations.
+   *   <li>JSR 330 annotations.
+   *   <li>Eager loading of singletons.
+   * </ul>
+   *
+   * <p><strong>Note that method injection is not supported.</strong>
+   */
+  public static <T> T inject(Class<T> type, Object... modules) {
+    Key key = new Key(type, null);
+    MiniGuice miniGuice = new MiniGuice();
+    for (Object module : modules) {
+      miniGuice.install(module);
+    }
+    miniGuice.requireKey(key, "root injection");
+    miniGuice.addJitBindings();
+    miniGuice.addProviderBindings();
+    miniGuice.eagerlyLoadSingletons();
+    Provider<?> provider = miniGuice.bindings.get(key);
+    return type.cast(provider.get());
+  }
+
+  private void addProviderBindings() {
+    Map<Key, Provider<?>> providerBindings = new HashMap<Key, Provider<?>>();
+    for (final Map.Entry<Key, Provider<?>> binding : bindings.entrySet()) {
+      Key key = binding.getKey();
+      final Provider<?> value = binding.getValue();
+      Provider<Provider<?>> providerProvider = new Provider<Provider<?>>() {
+        public Provider<?> get() {
+          return value;
+        }
+      };
+      providerBindings.put(new Key(new ProviderType(javax.inject.Provider.class, key.type),
+          key.annotation), providerProvider);
+    }
+    bindings.putAll(providerBindings);
+  }
+
+  private void requireKey(Key key, Object requiredBy) {
+    if (key.type instanceof ParameterizedType
+        && (((ParameterizedType) key.type).getRawType() == Provider.class
+        || ((ParameterizedType) key.type).getRawType() == javax.inject.Provider.class)) {
+      Type type = ((ParameterizedType) key.type).getActualTypeArguments()[0];
+      key = new Key(type, key.annotation);
+    }
+
+    requiredKeys.add(new RequiredKey(key, requiredBy));
+  }
+
+  private void eagerlyLoadSingletons() {
+    for (Key key : singletons) {
+      Provider<?> provider = bindings.get(key);
+      final Object onlyInstance = provider.get();
+      bindings.put(key, new Provider<Object>() {
+        public Object get() {
+          return onlyInstance;
+        }
+      });
+    }
+  }
+
+  public void install(Object module) {
+    boolean hasProvidesMethods = false;
+    for (Class<?> c = module.getClass(); c != Object.class; c = c.getSuperclass()) {
+      for (Method method : c.getDeclaredMethods()) {
+        if (method.isAnnotationPresent(com.google.inject.Provides.class)) {
+          Key key = key(method, method.getGenericReturnType(), method.getAnnotations());
+          addProviderMethodBinding(key, module, method);
+          hasProvidesMethods = true;
+        }
+      }
+    }
+    if (!hasProvidesMethods) {
+      throw new IllegalArgumentException("No @Provides methods on " + module);
+    }
+  }
+
+  private void addProviderMethodBinding(Key key, final Object instance, final Method method) {
+    final Key[] parameterKeys = parametersToKeys(
+        method, method.getGenericParameterTypes(), method.getParameterAnnotations());
+    method.setAccessible(true);
+    final Provider<Object> unscoped = new Provider<Object>() {
+      public Object get() {
+        Object[] parameters = keysToValues(parameterKeys);
+        try {
+          return method.invoke(instance, parameters);
+        } catch (IllegalAccessException e) {
+          throw new RuntimeException(e);
+        } catch (InvocationTargetException e) {
+          throw new RuntimeException(e.getCause());
+        }
+      }
+    };
+
+    boolean singleton = method.isAnnotationPresent(javax.inject.Singleton.class);
+    putBinding(key, unscoped, singleton);
+  }
+
+  private void addJitBindings() {
+    RequiredKey requiredKey;
+    while ((requiredKey = requiredKeys.poll()) != null) {
+      Key key = requiredKey.key;
+      if (bindings.containsKey(key)) {
+        continue;
+      }
+      if (!(key.type instanceof Class) || key.annotation != null) {
+        throw new IllegalArgumentException("No binding for " + key);
+      }
+      addJitBinding(key, requiredKey.requiredBy);
+    }
+  }
+
+  private void addJitBinding(Key key, Object requiredBy) {
+    Class<?> type = (Class<?>) key.type;
+
+    /*
+     * Lookup the injectable fields and their corresponding keys.
+     */
+    final List<Field> injectedFields = new ArrayList<Field>();
+    List<Object> fieldKeysList = new ArrayList<Object>();
+    for (Class<?> c = type; c != Object.class; c = c.getSuperclass()) {
+      for (Field field : c.getDeclaredFields()) {
+        if (!field.isAnnotationPresent(javax.inject.Inject.class)) {
+          continue;
+        }
+        field.setAccessible(true);
+        injectedFields.add(field);
+        Key fieldKey = key(field, field.getGenericType(), field.getAnnotations());
+        fieldKeysList.add(fieldKey);
+        requireKey(fieldKey, field);
+      }
+    }
+    final Key[] fieldKeys = fieldKeysList.toArray(new Key[fieldKeysList.size()]);
+
+    /*
+     * Lookup @Inject-annotated constructors. If there's no @Inject-annotated
+     * constructor, use a default constructor if the class has other injections.
+     */
+    Constructor<?> injectedConstructor = null;
+    for (Constructor<?> constructor : type.getDeclaredConstructors()) {
+      if (!constructor.isAnnotationPresent(javax.inject.Inject.class)) {
+        continue;
+      }
+      if (injectedConstructor != null) {
+        throw new IllegalArgumentException("Too many injectable constructors on " + type);
+      }
+      constructor.setAccessible(true);
+      injectedConstructor = constructor;
+    }
+    if (injectedConstructor == null) {
+      if (fieldKeys.length == 0) {
+        throw new IllegalArgumentException("No injectable constructor on "
+            + type + " required by " + requiredBy);
+      }
+      try {
+        injectedConstructor = type.getConstructor();
+      } catch (NoSuchMethodException e) {
+        throw new IllegalArgumentException("No injectable constructor on "
+            + type + " required by " + requiredBy);
+      }
+    }
+
+    /*
+     * Create a provider that invokes the constructor and sets its fields.
+     */
+    final Constructor<?> constructor = injectedConstructor;
+    final Key[] parameterKeys = parametersToKeys(
+        constructor, constructor.getGenericParameterTypes(), constructor.getParameterAnnotations());
+    final Provider<Object> unscoped = new Provider<Object>() {
+      public Object get() {
+        Object[] constructorParameters = keysToValues(parameterKeys);
+        try {
+          Object result = constructor.newInstance(constructorParameters);
+          Object[] fieldValues = keysToValues(fieldKeys);
+          for (int i = 0; i < fieldValues.length; i++) {
+            injectedFields.get(i).set(result, fieldValues[i]);
+          }
+          return result;
+        } catch (IllegalAccessException e) {
+          throw new RuntimeException(e.getCause());
+        } catch (InvocationTargetException e) {
+          throw new RuntimeException(e.getCause());
+        } catch (InstantiationException e) {
+          throw new RuntimeException(e);
+        }
+      }
+    };
+
+    boolean singleton = type.isAnnotationPresent(javax.inject.Singleton.class);
+    putBinding(new Key(type, null), unscoped, singleton);
+  }
+
+  private void putBinding(Key key, Provider<Object> provider, boolean singleton) {
+    if (singleton) {
+      singletons.add(key);
+      final Provider<Object> unscoped = provider;
+      provider = new Provider<Object>() {
+        private Object onlyInstance = UNINITIALIZED;
+        public Object get() {
+          if (onlyInstance == UNINITIALIZED) {
+            onlyInstance = unscoped.get();
+          }
+          return onlyInstance;
+        }
+      };
+    }
+
+    if (bindings.put(key, provider) != null) {
+      throw new IllegalArgumentException("Duplicate binding " + key);
+    }
+  }
+
+  private Object[] keysToValues(Key[] parameterKeys) {
+    Object[] parameters = new Object[parameterKeys.length];
+    for (int i = 0; i < parameterKeys.length; i++) {
+      parameters[i] = bindings.get(parameterKeys[i]).get();
+    }
+    return parameters;
+  }
+
+  private Key[] parametersToKeys(Member member, Type[] types, Annotation[][] annotations) {
+    final Key[] parameterKeys = new Key[types.length];
+    for (int i = 0; i < parameterKeys.length; i++) {
+      String name = member + " parameter " + i;
+      parameterKeys[i] = key(name, types[i], annotations[i]);
+      requireKey(parameterKeys[i], name);
+    }
+    return parameterKeys;
+  }
+
+  public Key key(Object subject, Type type, Annotation[] annotations) {
+    Annotation bindingAnnotation = null;
+    for (Annotation a : annotations) {
+      if (!a.annotationType().isAnnotationPresent(javax.inject.Qualifier.class)) {
+        continue;
+      }
+      if (bindingAnnotation != null) {
+        throw new IllegalArgumentException("Too many binding annotations on " + subject);
+      }
+      bindingAnnotation = a;
+    }
+    return new Key(type, bindingAnnotation);
+  }
+
+  private static boolean equal(Object a, Object b) {
+    return a == null ? b == null : a.equals(b);
+  }
+
+  private static final class Key {
+    final Type type;
+    final Annotation annotation;
+
+    Key(Type type, Annotation annotation) {
+      this.type = type;
+      this.annotation = annotation;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o instanceof Key
+          && ((Key) o).type.equals(type)
+          && equal(annotation, ((Key) o).annotation);
+    }
+
+    @Override public int hashCode() {
+      int result = type.hashCode();
+      if (annotation != null) {
+        result += (37 * annotation.hashCode());
+      }
+      return result;
+    }
+
+    @Override public String toString() {
+      return "key[type=" + type + ",annotation=" + annotation + "]";
+    }
+  }
+
+  private class RequiredKey {
+    private final Key key;
+    private final Object requiredBy;
+
+    private RequiredKey(Key key, Object requiredBy) {
+      this.key = key;
+      this.requiredBy = requiredBy;
+    }
+  }
+
+  private static final class ProviderType implements ParameterizedType {
+    private final Class<?> rawType;
+    private final Type typeArgument;
+
+    public ProviderType(Class<?> rawType, Type typeArgument) {
+      this.rawType = rawType;
+      this.typeArgument = typeArgument;
+    }
+
+    public Type getRawType() {
+      return rawType;
+    }
+
+    public Type[] getActualTypeArguments() {
+      return new Type[] { typeArgument };
+    }
+
+    public Type getOwnerType() {
+      return null;
+    }
+
+    @Override public boolean equals(Object o) {
+      if (o instanceof ParameterizedType) {
+        ParameterizedType that = (ParameterizedType) o;
+        return Arrays.equals(getActualTypeArguments(), that.getActualTypeArguments())
+            && that.getRawType() == rawType;
+      }
+      return false;
+    }
+
+    @Override public int hashCode() {
+      return Arrays.hashCode(getActualTypeArguments()) ^ rawType.hashCode();
+    }
+  }
+}
diff --git a/extensions/mini/test/com/google/inject/mini/MiniGuiceTest.java b/extensions/mini/test/com/google/inject/mini/MiniGuiceTest.java
new file mode 100644
index 0000000..e6df593
--- /dev/null
+++ b/extensions/mini/test/com/google/inject/mini/MiniGuiceTest.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2010 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.inject.mini;
+
+import com.google.inject.Provides;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+public final class MiniGuiceTest extends TestCase {
+
+  public void testBasicInjection() {
+    G g = MiniGuice.inject(G.class, new Object() {
+      @Provides E provideE(F f) {
+        return new E(f);
+      }
+      @Provides F provideF() {
+        return new F();
+      }
+    });
+
+    assertNotNull(g.a);
+    assertNotNull(g.b);
+    assertNotNull(g.c);
+    assertNotNull(g.d);
+    assertNotNull(g.e);
+    assertNotNull(g.e.f);
+  }
+
+  static class A {
+    @Inject A() {}
+  }
+
+  static class B {
+    @Inject B() {}
+  }
+
+  @Singleton
+  static class C {
+    @Inject C() {}
+  }
+
+  @Singleton
+  static class D {
+    @Inject D() {}
+  }
+
+  static class E {
+    F f;
+    E(F f) {
+      this.f = f;
+    }
+  }
+
+  static class F {}
+
+  static class G {
+    @Inject A a;
+    @Inject B b;
+    C c;
+    D d;
+    @Inject E e;
+    @Inject G(C c, D d) {
+      this.c = c;
+      this.d = d;
+    }
+  }
+  
+  public void testProviderInjection() {
+    H h = MiniGuice.inject(H.class);
+    assertNotNull(h.aProvider.get());
+    assertNotNull(h.aProvider.get());
+    assertNotSame(h.aProvider.get(), h.aProvider.get());
+  }
+
+  static class H {
+    @Inject Provider<A> aProvider;
+    @Inject H() {}
+  }
+  
+  public void testSingletons() {
+    J j = MiniGuice.inject(J.class, new Object() {
+      @Provides @Singleton F provideK() {
+        return new F();
+      }
+    });
+    assertSame(j.fProvider.get(), j.fProvider.get());
+    assertSame(j.iProvider.get(), j.iProvider.get());
+  }
+
+  @Singleton
+  static class I {
+    @Inject I() {}
+  }
+
+  static class J {
+    @Inject Provider<F> fProvider;
+    @Inject Provider<I> iProvider;
+    @Inject J() {}
+  }
+
+  public void testBindingAnnotations() {
+    final A one = new A();
+    final A two = new A();
+
+    K k = MiniGuice.inject(K.class, new Object() {
+      @Provides @Named("one") A getOne() {
+        return one;
+      }
+      @Provides @Named("two") A getTwo() {
+        return two;
+      }
+    });
+
+    assertNotNull(k.a);
+    assertSame(one, k.aOne);
+    assertSame(two, k.aTwo);
+  }
+
+  public static class K {
+    @Inject A a;
+    @Inject @Named("one") A aOne;
+    @Inject @Named("two") A aTwo;
+  }
+  
+  public void testSingletonBindingAnnotationAndProvider() {
+    final AtomicReference<A> a1 = new AtomicReference<A>();
+    final AtomicReference<A> a2 = new AtomicReference<A>();
+
+    L l = MiniGuice.inject(L.class, new Object() {
+      @Provides @Singleton @Named("one") F provideF(Provider<A> aProvider) {
+        a1.set(aProvider.get());
+        a2.set(aProvider.get());
+        return new F();
+      }
+    });
+
+    assertNotNull(a1.get());
+    assertNotNull(a2.get());
+    assertNotSame(a1.get(), a2.get());
+    assertSame(l, l.lProvider.get());
+  }
+
+  @Singleton
+  public static class L {
+    @Inject @Named("one") F f;
+    @Inject Provider<L> lProvider;
+  }
+
+  public void testSingletonInGraph() {
+    M m = MiniGuice.inject(M.class, new Object() {
+      @Provides @Singleton F provideF() {
+        return new F();
+      }
+    });
+
+    assertSame(m.f1, m.f2);
+    assertSame(m.f1, m.n1.f1);
+    assertSame(m.f1, m.n1.f2);
+    assertSame(m.f1, m.n2.f1);
+    assertSame(m.f1, m.n2.f2);
+    assertSame(m.f1, m.n1.fProvider.get());
+    assertSame(m.f1, m.n2.fProvider.get());
+  }
+
+  public static class M {
+    @Inject N n1;
+    @Inject N n2;
+    @Inject F f1;
+    @Inject F f2;
+  }
+
+  public static class N {
+    @Inject F f1;
+    @Inject F f2;
+    @Inject Provider<F> fProvider;
+  }
+
+  public void testNoJitBindingsForAnnotations() {
+    try {
+      MiniGuice.inject(O.class);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public static class O {
+    @Inject @Named("a") A a;
+  }
+
+  public void testSubclasses() {
+    Q q = MiniGuice.inject(Q.class, new Object() {
+      @Provides F provideF() {
+        return new F();
+      }
+    });
+
+    assertNotNull(q.f);
+  }
+  
+  public static class P {
+    @Inject F f;
+  }
+
+  public static class Q extends P {
+    @Inject Q() {}
+  }
+  
+  public void testSingletonsAreEager() {
+    final AtomicBoolean sInjected = new AtomicBoolean();
+
+    R.injected = false;
+    MiniGuice.inject(A.class, new Object() {
+      @Provides F provideF(R r) {
+        return new F();
+      }
+
+      @Provides @Singleton S provideS() {
+        sInjected.set(true);
+        return new S();
+      }
+    });
+
+    assertTrue(R.injected);
+    assertTrue(sInjected.get());
+  }
+
+  @Singleton
+  static class R {
+    static boolean injected = false;
+    @Inject R() {
+      injected = true;
+    }
+  }
+
+  static class S {}
+}
diff --git a/extensions/multibindings/.gitignore b/extensions/multibindings/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/extensions/multibindings/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/extensions/multibindings/build.properties b/extensions/multibindings/build.properties
new file mode 100644
index 0000000..77228a8
--- /dev/null
+++ b/extensions/multibindings/build.properties
@@ -0,0 +1,7 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.multibindings.AllTests
+module=com.google.inject.multibindings
+fragment=true
diff --git a/extensions/multibindings/build.xml b/extensions/multibindings/build.xml
new file mode 100644
index 0000000..f78a8e3
--- /dev/null
+++ b/extensions/multibindings/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-multibindings" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/multibindings/pom.xml b/extensions/multibindings/pom.xml
new file mode 100644
index 0000000..4f75b28
--- /dev/null
+++ b/extensions/multibindings/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-multibindings</artifactId>
+
+  <name>Google Guice - Extensions - MultiBindings</name>
+
+</project>
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/ClassMapKey.java b/extensions/multibindings/src/com/google/inject/multibindings/ClassMapKey.java
new file mode 100644
index 0000000..d12fe60
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/ClassMapKey.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2015 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.inject.multibindings;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Allows {@literal @}{@link ProvidesIntoMap} to specify a class map key.
+ *
+ * @since 4.0
+ */
+@MapKey(unwrapValue = true)
+@Documented
+@Target(METHOD)
+@Retention(RUNTIME)
+public @interface ClassMapKey {
+  Class<?> value();
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/Element.java b/extensions/multibindings/src/com/google/inject/multibindings/Element.java
new file mode 100644
index 0000000..c675551
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/Element.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 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.inject.multibindings;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.Retention;
+
+/**
+ * An internal binding annotation applied to each element in a multibinding.
+ * All elements are assigned a globally-unique id to allow different modules
+ * to contribute multibindings independently.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+@Retention(RUNTIME) @BindingAnnotation
+@interface Element {
+
+  enum Type {
+    MAPBINDER,
+    MULTIBINDER,
+    OPTIONALBINDER;
+  }
+
+  String setName();
+  int uniqueId();
+  Type type();
+  String keyType();
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/Indexer.java b/extensions/multibindings/src/com/google/inject/multibindings/Indexer.java
new file mode 100644
index 0000000..4edcf76
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/Indexer.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (C) 2014 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.inject.multibindings;
+
+import com.google.common.base.Objects;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Scope;
+import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.BindingScopingVisitor;
+import com.google.inject.spi.ConstructorBinding;
+import com.google.inject.spi.ConvertedConstantBinding;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.ExposedBinding;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.LinkedKeyBinding;
+import com.google.inject.spi.ProviderBinding;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderKeyBinding;
+import com.google.inject.spi.UntargettedBinding;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Visits bindings to return a {@code IndexedBinding} that can be used to emulate the binding
+ * deduplication that Guice internally performs.
+ */
+class Indexer extends DefaultBindingTargetVisitor<Object, Indexer.IndexedBinding>
+    implements BindingScopingVisitor<Object> {
+  enum BindingType {
+    INSTANCE,
+    PROVIDER_INSTANCE,
+    PROVIDER_KEY,
+    LINKED_KEY,
+    UNTARGETTED,
+    CONSTRUCTOR,
+    CONSTANT,
+    EXPOSED,
+    PROVIDED_BY,
+  }
+
+  static class IndexedBinding {
+    final String annotationName;
+    final Element.Type annotationType;
+    final TypeLiteral<?> typeLiteral;
+    final Object scope;
+    final BindingType type;
+    final Object extraEquality;
+
+    IndexedBinding(Binding<?> binding, BindingType type, Object scope, Object extraEquality) {
+      this.scope = scope;
+      this.type = type;
+      this.extraEquality = extraEquality;
+      this.typeLiteral = binding.getKey().getTypeLiteral();
+      Element annotation = (Element) binding.getKey().getAnnotation();
+      this.annotationName = annotation.setName();
+      this.annotationType = annotation.type();
+    }
+
+    @Override public boolean equals(Object obj) {
+      if (!(obj instanceof IndexedBinding)) {
+        return false;
+      }
+      IndexedBinding o = (IndexedBinding) obj;
+      return type == o.type
+          && Objects.equal(scope, o.scope)
+          && typeLiteral.equals(o.typeLiteral)
+          && annotationType == o.annotationType
+          && annotationName.equals(o.annotationName)
+          && Objects.equal(extraEquality, o.extraEquality);
+    }
+
+    @Override public int hashCode() {
+      return Objects.hashCode(type, scope, typeLiteral, annotationType, annotationName,
+          extraEquality);
+    }
+  }
+
+  final Injector injector;
+
+  Indexer(Injector injector) {
+    this.injector = injector;
+  }
+
+  boolean isIndexable(Binding<?> binding) {
+    return binding.getKey().getAnnotation() instanceof Element;
+  }
+
+  private Object scope(Binding<?> binding) {
+    return binding.acceptScopingVisitor(this);
+  }
+
+  @Override public Indexer.IndexedBinding visit(ConstructorBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.CONSTRUCTOR, scope(binding),
+        binding.getConstructor());
+  }
+
+  @Override public Indexer.IndexedBinding visit(
+      ConvertedConstantBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.CONSTANT, scope(binding),
+        binding.getValue());
+  }
+
+  @Override public Indexer.IndexedBinding visit(ExposedBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.EXPOSED, scope(binding), binding);
+  }
+
+  @Override public Indexer.IndexedBinding visit(InstanceBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.INSTANCE, scope(binding),
+        binding.getInstance());
+  }
+
+  @Override public Indexer.IndexedBinding visit(LinkedKeyBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.LINKED_KEY, scope(binding),
+        binding.getLinkedKey());
+  }
+
+  @Override public Indexer.IndexedBinding visit(ProviderBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.PROVIDED_BY, scope(binding),
+        injector.getBinding(binding.getProvidedKey()));
+  }
+
+  @Override public Indexer.IndexedBinding visit(ProviderInstanceBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.PROVIDER_INSTANCE, scope(binding),
+        binding.getUserSuppliedProvider());
+  }
+
+  @Override public Indexer.IndexedBinding visit(ProviderKeyBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.PROVIDER_KEY, scope(binding),
+        binding.getProviderKey());
+  }
+
+  @Override public Indexer.IndexedBinding visit(UntargettedBinding<? extends Object> binding) {
+    return new Indexer.IndexedBinding(binding, BindingType.UNTARGETTED, scope(binding), null);
+  }
+  
+  private static final Object EAGER_SINGLETON = new Object();
+  
+  @Override public Object visitEagerSingleton() {
+    return EAGER_SINGLETON;
+  }
+
+  @Override public Object visitNoScoping() {
+    return Scopes.NO_SCOPE;
+  }
+
+  @Override public Object visitScope(Scope scope) {
+    return scope;
+  }
+
+  @Override public Object visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
+    return scopeAnnotation;
+  }
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java b/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
new file mode 100644
index 0000000..fc3d74f
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
@@ -0,0 +1,854 @@
+/**
+ * Copyright (C) 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.inject.multibindings;
+
+import static com.google.inject.multibindings.Element.Type.MAPBINDER;
+import static com.google.inject.multibindings.Multibinder.checkConfiguration;
+import static com.google.inject.multibindings.Multibinder.checkNotNull;
+import static com.google.inject.multibindings.Multibinder.setOf;
+import static com.google.inject.util.Types.newParameterizedType;
+import static com.google.inject.util.Types.newParameterizedTypeWithOwner;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
+import com.google.common.base.Supplier;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.Sets;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.internal.Errors;
+import com.google.inject.multibindings.Indexer.IndexedBinding;
+import com.google.inject.multibindings.Multibinder.RealMultibinder;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderLookup;
+import com.google.inject.spi.ProviderWithDependencies;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+import com.google.inject.spi.Toolable;
+import com.google.inject.util.Types;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * An API to bind multiple map entries separately, only to later inject them as
+ * a complete map. MapBinder is intended for use in your application's module:
+ * <pre><code>
+ * public class SnacksModule extends AbstractModule {
+ *   protected void configure() {
+ *     MapBinder&lt;String, Snack&gt; mapbinder
+ *         = MapBinder.newMapBinder(binder(), String.class, Snack.class);
+ *     mapbinder.addBinding("twix").toInstance(new Twix());
+ *     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
+ *     mapbinder.addBinding("skittles").to(Skittles.class);
+ *   }
+ * }</code></pre>
+ *
+ * <p>With this binding, a {@link Map}{@code <String, Snack>} can now be
+ * injected:
+ * <pre><code>
+ * class SnackMachine {
+ *   {@literal @}Inject
+ *   public SnackMachine(Map&lt;String, Snack&gt; snacks) { ... }
+ * }</code></pre>
+ *
+ * <p>In addition to binding {@code Map<K, V>}, a mapbinder will also bind
+ * {@code Map<K, Provider<V>>} for lazy value provision:
+ * <pre><code>
+ * class SnackMachine {
+ *   {@literal @}Inject
+ *   public SnackMachine(Map&lt;String, Provider&lt;Snack&gt;&gt; snackProviders) { ... }
+ * }</code></pre>
+ *
+ * <p>Contributing mapbindings from different modules is supported. For example,
+ * it is okay to have both {@code CandyModule} and {@code ChipsModule} both
+ * create their own {@code MapBinder<String, Snack>}, and to each contribute
+ * bindings to the snacks map. When that map is injected, it will contain
+ * entries from both modules.
+ *
+ * <p>The map's iteration order is consistent with the binding order. This is
+ * convenient when multiple elements are contributed by the same module because
+ * that module can order its bindings appropriately. Avoid relying on the
+ * iteration order of elements contributed by different modules, since there is
+ * no equivalent mechanism to order modules.
+ *
+ * <p>The map is unmodifiable.  Elements can only be added to the map by
+ * configuring the MapBinder.  Elements can never be removed from the map.
+ *
+ * <p>Values are resolved at map injection time. If a value is bound to a
+ * provider, that provider's get method will be called each time the map is
+ * injected (unless the binding is also scoped, or a map of providers is injected).
+ *
+ * <p>Annotations are used to create different maps of the same key/value
+ * type. Each distinct annotation gets its own independent map.
+ *
+ * <p><strong>Keys must be distinct.</strong> If the same key is bound more than
+ * once, map injection will fail. However, use {@link #permitDuplicates()} in
+ * order to allow duplicate keys; extra bindings to {@code Map<K, Set<V>>} and
+ * {@code Map<K, Set<Provider<V>>} will be added.
+ *
+ * <p><strong>Keys must be non-null.</strong> {@code addBinding(null)} will
+ * throw an unchecked exception.
+ *
+ * <p><strong>Values must be non-null to use map injection.</strong> If any
+ * value is null, map injection will fail (although injecting a map of providers
+ * will not).
+ *
+ * @author dpb@google.com (David P. Baker)
+ */
+public abstract class MapBinder<K, V> {
+  private MapBinder() {}
+
+  /**
+   * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+   * {@link Map} that is itself bound with no binding annotation.
+   */
+  public static <K, V> MapBinder<K, V> newMapBinder(Binder binder,
+      TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
+    binder = binder.skipSources(MapBinder.class, RealMapBinder.class);
+    return newRealMapBinder(binder, keyType, valueType, Key.get(mapOf(keyType, valueType)),
+        Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType)));
+  }
+
+  /**
+   * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+   * {@link Map} that is itself bound with no binding annotation.
+   */
+  public static <K, V> MapBinder<K, V> newMapBinder(Binder binder,
+      Class<K> keyType, Class<V> valueType) {
+    return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType));
+  }
+
+  /**
+   * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+   * {@link Map} that is itself bound with {@code annotation}.
+   */
+  public static <K, V> MapBinder<K, V> newMapBinder(Binder binder,
+      TypeLiteral<K> keyType, TypeLiteral<V> valueType, Annotation annotation) {
+    binder = binder.skipSources(MapBinder.class, RealMapBinder.class);
+    return newRealMapBinder(binder, keyType, valueType,
+        Key.get(mapOf(keyType, valueType), annotation),
+        Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType), annotation));
+  }
+
+  /**
+   * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+   * {@link Map} that is itself bound with {@code annotation}.
+   */
+  public static <K, V> MapBinder<K, V> newMapBinder(Binder binder,
+      Class<K> keyType, Class<V> valueType, Annotation annotation) {
+    return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotation);
+  }
+
+  /**
+   * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+   * {@link Map} that is itself bound with {@code annotationType}.
+   */
+  public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, TypeLiteral<K> keyType,
+      TypeLiteral<V> valueType, Class<? extends Annotation> annotationType) {
+    binder = binder.skipSources(MapBinder.class, RealMapBinder.class);
+    return newRealMapBinder(binder, keyType, valueType,
+        Key.get(mapOf(keyType, valueType), annotationType),
+        Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType), annotationType));
+  }
+
+  /**
+   * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+   * {@link Map} that is itself bound with {@code annotationType}.
+   */
+  public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, Class<K> keyType,
+      Class<V> valueType, Class<? extends Annotation> annotationType) {
+    return newMapBinder(
+        binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotationType);
+  }
+
+  @SuppressWarnings("unchecked") // a map of <K, V> is safely a Map<K, V>
+  static <K, V> TypeLiteral<Map<K, V>> mapOf(
+      TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
+    return (TypeLiteral<Map<K, V>>) TypeLiteral.get(
+        Types.mapOf(keyType.getType(), valueType.getType()));
+  }
+
+  @SuppressWarnings("unchecked") // a provider map <K, V> is safely a Map<K, Provider<V>>
+  static <K, V> TypeLiteral<Map<K, Provider<V>>> mapOfProviderOf(
+      TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
+    return (TypeLiteral<Map<K, Provider<V>>>) TypeLiteral.get(
+        Types.mapOf(keyType.getType(), Types.providerOf(valueType.getType())));
+  }
+  
+  // provider map <K, V> is safely a Map<K, javax.inject.Provider<V>>>
+  @SuppressWarnings("unchecked")
+  static <K, V> TypeLiteral<Map<K, javax.inject.Provider<V>>> mapOfJavaxProviderOf(
+      TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
+    return (TypeLiteral<Map<K, javax.inject.Provider<V>>>) TypeLiteral.get(
+        Types.mapOf(keyType.getType(),
+            newParameterizedType(javax.inject.Provider.class, valueType.getType())));
+  }
+
+  @SuppressWarnings("unchecked") // a provider map <K, Set<V>> is safely a Map<K, Set<Provider<V>>>
+  static <K, V> TypeLiteral<Map<K, Set<Provider<V>>>> mapOfSetOfProviderOf(
+      TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
+    return (TypeLiteral<Map<K, Set<Provider<V>>>>) TypeLiteral.get(
+        Types.mapOf(keyType.getType(), Types.setOf(Types.providerOf(valueType.getType()))));
+  }
+
+  @SuppressWarnings("unchecked") // a provider entry <K, V> is safely a Map.Entry<K, Provider<V>>
+  static <K, V> TypeLiteral<Map.Entry<K, Provider<V>>> entryOfProviderOf(
+      TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
+    return (TypeLiteral<Entry<K, Provider<V>>>) TypeLiteral.get(newParameterizedTypeWithOwner(
+        Map.class, Entry.class, keyType.getType(), Types.providerOf(valueType.getType())));
+  }
+
+  // Note: We use valueTypeAndAnnotation effectively as a Pair<TypeLiteral, Annotation|Class>
+  // since it's an easy way to group a type and an optional annotation type or instance.
+  static <K, V> RealMapBinder<K, V> newRealMapBinder(Binder binder, TypeLiteral<K> keyType,
+      Key<V> valueTypeAndAnnotation) {
+    binder = binder.skipSources(MapBinder.class, RealMapBinder.class);
+    TypeLiteral<V> valueType = valueTypeAndAnnotation.getTypeLiteral();
+    return newRealMapBinder(binder, keyType, valueType,
+        valueTypeAndAnnotation.ofType(mapOf(keyType, valueType)),
+        Multibinder.newSetBinder(binder,
+            valueTypeAndAnnotation.ofType(entryOfProviderOf(keyType, valueType))));
+  }
+
+  private static <K, V> RealMapBinder<K, V> newRealMapBinder(Binder binder,
+      TypeLiteral<K> keyType, TypeLiteral<V> valueType, Key<Map<K, V>> mapKey,
+      Multibinder<Entry<K, Provider<V>>> entrySetBinder) {
+    RealMapBinder<K, V> mapBinder =
+        new RealMapBinder<K, V>(binder, keyType, valueType, mapKey, entrySetBinder);
+    binder.install(mapBinder);
+    return mapBinder;
+  }
+
+  /**
+   * Configures the {@code MapBinder} to handle duplicate entries.
+   * <p>When multiple equal keys are bound, the value that gets included in the map is
+   * arbitrary.
+   * <p>In addition to the {@code Map<K, V>} and {@code Map<K, Provider<V>>}
+   * maps that are normally bound, a {@code Map<K, Set<V>>} and
+   * {@code Map<K, Set<Provider<V>>>} are <em>also</em> bound, which contain
+   * all values bound to each key.
+   * <p>
+   * When multiple modules contribute elements to the map, this configuration
+   * option impacts all of them.
+   *
+   * @return this map binder
+   * @since 3.0
+   */
+  public abstract MapBinder<K, V> permitDuplicates();
+
+  /**
+   * Returns a binding builder used to add a new entry in the map. Each
+   * key must be distinct (and non-null). Bound providers will be evaluated each
+   * time the map is injected.
+   *
+   * <p>It is an error to call this method without also calling one of the
+   * {@code to} methods on the returned binding builder.
+   *
+   * <p>Scoping elements independently is supported. Use the {@code in} method
+   * to specify a binding scope.
+   */
+  public abstract LinkedBindingBuilder<V> addBinding(K key);
+
+  /**
+   * The actual mapbinder plays several roles:
+   *
+   * <p>As a MapBinder, it acts as a factory for LinkedBindingBuilders for
+   * each of the map's values. It delegates to a {@link Multibinder} of
+   * entries (keys to value providers).
+   *
+   * <p>As a Module, it installs the binding to the map itself, as well as to
+   * a corresponding map whose values are providers. It uses the entry set
+   * multibinder to construct the map and the provider map.
+   *
+   * <p>As a module, this implements equals() and hashcode() in order to trick
+   * Guice into executing its configure() method only once. That makes it so
+   * that multiple mapbinders can be created for the same target map, but
+   * only one is bound. Since the list of bindings is retrieved from the
+   * injector itself (and not the mapbinder), each mapbinder has access to
+   * all contributions from all equivalent mapbinders.
+   *
+   * <p>Rather than binding a single Map.Entry&lt;K, V&gt;, the map binder
+   * binds keys and values independently. This allows the values to be properly
+   * scoped.
+   *
+   * <p>We use a subclass to hide 'implements Module' from the public API.
+   */
+  static final class RealMapBinder<K, V> extends MapBinder<K, V> implements Module {
+    private final TypeLiteral<K> keyType;
+    private final TypeLiteral<V> valueType;
+    private final Key<Map<K, V>> mapKey;
+    private final Key<Map<K, javax.inject.Provider<V>>> javaxProviderMapKey;
+    private final Key<Map<K, Provider<V>>> providerMapKey;
+    private final Key<Map<K, Set<V>>> multimapKey;
+    private final Key<Map<K, Set<Provider<V>>>> providerMultimapKey;
+    private final RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder;
+    private final Map<K, String> duplicateKeyErrorMessages;
+
+    /* the target injector's binder. non-null until initialization, null afterwards */
+    private Binder binder;
+
+    private boolean permitDuplicates;
+    private ImmutableList<Map.Entry<K, Binding<V>>> mapBindings;
+
+    private RealMapBinder(Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType,
+        Key<Map<K, V>> mapKey, Multibinder<Map.Entry<K, Provider<V>>> entrySetBinder) {
+      this.keyType = keyType;
+      this.valueType = valueType;
+      this.mapKey = mapKey;
+      this.providerMapKey = mapKey.ofType(mapOfProviderOf(keyType, valueType));
+      this.javaxProviderMapKey = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType));
+      this.multimapKey = mapKey.ofType(mapOf(keyType, setOf(valueType)));
+      this.providerMultimapKey = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType));
+      this.entrySetBinder = (RealMultibinder<Entry<K, Provider<V>>>) entrySetBinder;
+      this.binder = binder;
+      this.duplicateKeyErrorMessages = Maps.newHashMap();
+    }
+    
+    /** Sets the error message to be shown if the key had duplicate non-equal bindings. */
+    void updateDuplicateKeyMessage(K k, String errMsg) {
+      duplicateKeyErrorMessages.put(k, errMsg);
+    }
+
+    @Override
+    public MapBinder<K, V> permitDuplicates() {
+      entrySetBinder.permitDuplicates();
+      binder.install(new MultimapBinder<K, V>(
+          multimapKey, providerMultimapKey, entrySetBinder.getSetKey()));
+      return this;
+    }
+    
+    Key<V> getKeyForNewValue(K key) {
+      checkNotNull(key, "key");
+      checkConfiguration(!isInitialized(), "MapBinder was already initialized");
+
+      Key<V> valueKey = Key.get(valueType,
+          new RealElement(entrySetBinder.getSetName(), MAPBINDER, keyType.toString()));
+      entrySetBinder.addBinding().toProvider(new ProviderMapEntry<K, V>(
+          key, binder.getProvider(valueKey), valueKey));
+      return valueKey;
+    }
+
+    /**
+     * This creates two bindings. One for the {@code Map.Entry<K, Provider<V>>}
+     * and another for {@code V}.
+     */
+    @Override public LinkedBindingBuilder<V> addBinding(K key) {
+      return binder.bind(getKeyForNewValue(key));
+    }
+
+    @Override public void configure(Binder binder) {
+      checkConfiguration(!isInitialized(), "MapBinder was already initialized");
+
+      ImmutableSet<Dependency<?>> dependencies
+          = ImmutableSet.<Dependency<?>>of(Dependency.get(entrySetBinder.getSetKey()));
+
+      // Binds a Map<K, Provider<V>> from a collection of Set<Entry<K, Provider<V>>.
+      Provider<Set<Entry<K, Provider<V>>>> entrySetProvider = binder
+          .getProvider(entrySetBinder.getSetKey());
+
+      binder.bind(providerMapKey).toProvider(
+          new RealProviderMapProvider(dependencies, entrySetProvider));
+
+      // The map this exposes is internally an ImmutableMap, so it's OK to massage
+      // the guice Provider to javax Provider in the value (since Guice provider
+      // implements javax Provider).
+      @SuppressWarnings("unchecked")
+      Key massagedProviderMapKey = (Key)providerMapKey;
+      binder.bind(javaxProviderMapKey).to(massagedProviderMapKey);
+
+      Provider<Map<K, Provider<V>>> mapProvider = binder.getProvider(providerMapKey);
+      binder.bind(mapKey).toProvider(new RealMapProvider(dependencies, mapProvider));
+    }
+
+    boolean containsElement(Element element) {
+      if (entrySetBinder.containsElement(element)) {
+        return true;
+      } else {
+        Key<?> key;
+        if (element instanceof Binding) {
+          key = ((Binding<?>)element).getKey();
+        } else if (element instanceof ProviderLookup) {
+          key = ((ProviderLookup<?>)element).getKey();
+        } else {
+          return false; // cannot match;
+        }
+
+        return key.equals(mapKey)
+            || key.equals(providerMapKey)
+            || key.equals(javaxProviderMapKey)
+            || key.equals(multimapKey)
+            || key.equals(providerMultimapKey)
+            || key.equals(entrySetBinder.getSetKey())
+            || matchesValueKey(key);
+        }
+    }
+
+    /** Returns true if the key indicates this is a value in the map. */
+    private boolean matchesValueKey(Key<?> key) {
+      return key.getAnnotation() instanceof RealElement
+          && ((RealElement) key.getAnnotation()).setName().equals(entrySetBinder.getSetName())
+          && ((RealElement) key.getAnnotation()).type() == MAPBINDER
+          && ((RealElement) key.getAnnotation()).keyType().equals(keyType.toString())
+          && key.getTypeLiteral().equals(valueType);
+    }
+
+    private boolean isInitialized() {
+      return binder == null;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o instanceof RealMapBinder
+          && ((RealMapBinder<?, ?>) o).mapKey.equals(mapKey);
+    }
+
+    @Override public int hashCode() {
+      return mapKey.hashCode();
+    }
+
+    final class RealProviderMapProvider
+        extends RealMapBinderProviderWithDependencies<Map<K, Provider<V>>> {
+      private final ImmutableSet<Dependency<?>> dependencies;
+      private final Provider<Set<Entry<K, Provider<V>>>> entrySetProvider;
+      private Map<K, Provider<V>> providerMap;
+
+      private RealProviderMapProvider(
+          ImmutableSet<Dependency<?>> dependencies,
+          Provider<Set<Entry<K, Provider<V>>>> entrySetProvider) {
+        super(mapKey);
+        this.dependencies = dependencies;
+        this.entrySetProvider = entrySetProvider;
+      }
+
+      @Toolable @Inject void initialize(Injector injector) {
+        RealMapBinder.this.binder = null;
+        permitDuplicates = entrySetBinder.permitsDuplicates(injector);
+
+        Map<K, Provider<V>> providerMapMutable = new LinkedHashMap<K, Provider<V>>();
+        List<Map.Entry<K, Binding<V>>> bindingsMutable = Lists.newArrayList();
+        Indexer indexer = new Indexer(injector);
+        Multimap<K, IndexedBinding> index = HashMultimap.create();
+        Set<K> duplicateKeys = null;
+        for (Entry<K, Provider<V>> entry : entrySetProvider.get()) {
+          ProviderMapEntry<K, V> providerEntry = (ProviderMapEntry<K, V>) entry;
+          Key<V> valueKey = providerEntry.getValueKey();
+          Binding<V> valueBinding = injector.getBinding(valueKey);
+          // If this isn't a dup due to an exact same binding, add it.
+          if (index.put(providerEntry.getKey(), valueBinding.acceptTargetVisitor(indexer))) {
+            Provider<V> previous = providerMapMutable.put(providerEntry.getKey(),
+                new ValueProvider<V>(providerEntry.getValue(), valueBinding));
+            if (previous != null && !permitDuplicates) {
+              if (duplicateKeys == null) {
+                duplicateKeys = Sets.newHashSet();
+              }
+              duplicateKeys.add(providerEntry.getKey());
+            }
+            bindingsMutable.add(Maps.immutableEntry(providerEntry.getKey(), valueBinding));
+          }
+        }
+        if (duplicateKeys != null) {
+          // Must use a ListMultimap in case more than one binding has the same source
+          // and is listed multiple times.
+          Multimap<K, String> dups = newLinkedKeyArrayValueMultimap();
+          for (Map.Entry<K, Binding<V>> entry : bindingsMutable) {
+            if (duplicateKeys.contains(entry.getKey())) {
+              dups.put(entry.getKey(), "\t at " + Errors.convert(entry.getValue().getSource()));
+            }
+          }
+          StringBuilder sb = new StringBuilder("Map injection failed due to duplicated key ");
+          boolean first = true;
+          for (K key : dups.keySet()) {
+            if (first) {
+              first = false;
+              if (duplicateKeyErrorMessages.containsKey(key)) {
+                sb.setLength(0);
+                sb.append(duplicateKeyErrorMessages.get(key));
+              } else {
+                sb.append("\"" + key + "\", from bindings:\n");
+              }
+            } else {
+              if (duplicateKeyErrorMessages.containsKey(key)) {
+                sb.append("\n and " + duplicateKeyErrorMessages.get(key));
+              } else {
+                sb.append("\n and key: \"" + key + "\", from bindings:\n");
+              }
+            }
+            Joiner.on('\n').appendTo(sb, dups.get(key)).append("\n");
+          }
+          checkConfiguration(false, sb.toString());
+        }
+
+        providerMap = ImmutableMap.copyOf(providerMapMutable);
+        mapBindings = ImmutableList.copyOf(bindingsMutable);
+      }
+
+      @Override public Map<K, Provider<V>> get() {
+        return providerMap;
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        return dependencies;
+      }
+    }
+
+    final class RealMapProvider extends RealMapWithExtensionProvider<Map<K, V>> {
+      private final ImmutableSet<Dependency<?>> dependencies;
+      private final Provider<Map<K, Provider<V>>> mapProvider;
+
+      private RealMapProvider(
+          ImmutableSet<Dependency<?>> dependencies,
+          Provider<Map<K, Provider<V>>> mapProvider) {
+        super(mapKey);
+        this.dependencies = dependencies;
+        this.mapProvider = mapProvider;
+      }
+
+      @Override public Map<K, V> get() {
+        // We can initialize the internal table efficiently this way and then swap the values
+        // one by one.
+        Map<K, Object> map = new LinkedHashMap<K, Object>(mapProvider.get());
+        for (Entry<K, Object> entry : map.entrySet()) {
+          @SuppressWarnings("unchecked")  // we initialized the entries with providers
+          ValueProvider<V> provider = (ValueProvider<V>)entry.getValue();
+          V value = provider.get();
+          checkConfiguration(value != null,
+              "Map injection failed due to null value for key \"%s\", bound at: %s",
+              entry.getKey(),
+              provider.getValueBinding().getSource());
+          entry.setValue(value);
+        }
+        @SuppressWarnings("unchecked")  // if we exited the loop then we replaced all Providers
+        Map<K, V> typedMap = (Map<K, V>) map;
+        return Collections.unmodifiableMap(typedMap);
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        return dependencies;
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public <B, R> R acceptExtensionVisitor(BindingTargetVisitor<B, R> visitor,
+          ProviderInstanceBinding<? extends B> binding) {
+        if (visitor instanceof MultibindingsTargetVisitor) {
+          return ((MultibindingsTargetVisitor<Map<K, V>, R>)visitor).visit(this);
+        } else {
+          return visitor.visit(binding);
+        }
+      }
+
+      @Override public Key<Map<K, V>> getMapKey() {
+        return mapKey;
+      }
+
+      @Override public TypeLiteral<?> getKeyTypeLiteral() {
+        return keyType;
+      }
+
+      @Override public TypeLiteral<?> getValueTypeLiteral() {
+        return valueType;
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public List<Entry<?, Binding<?>>> getEntries() {
+        if (isInitialized()) {
+          return (List)mapBindings; // safe because mapBindings is immutable
+        } else {
+          throw new UnsupportedOperationException(
+              "getElements() not supported for module bindings");
+        }
+      }
+
+      @Override public boolean permitsDuplicates() {
+        if (isInitialized()) {
+          return permitDuplicates;
+        } else {
+          throw new UnsupportedOperationException(
+              "permitsDuplicates() not supported for module bindings");
+        }
+      }
+
+      @Override public boolean containsElement(Element element) {
+        return RealMapBinder.this.containsElement(element);
+      }
+    }
+
+    /**
+     * Binds {@code Map<K, Set<V>>} and {{@code Map<K, Set<Provider<V>>>}.
+     */
+    static final class MultimapBinder<K, V> implements Module {
+
+      private final Key<Map<K, Set<V>>> multimapKey;
+      private final Key<Map<K, Set<Provider<V>>>> providerMultimapKey;
+      private final Key<Set<Entry<K,Provider<V>>>> entrySetKey;
+
+      public MultimapBinder(
+          Key<Map<K, Set<V>>> multimapKey,
+          Key<Map<K, Set<Provider<V>>>> providerMultimapKey,
+          Key<Set<Entry<K,Provider<V>>>> entrySetKey) {
+        this.multimapKey = multimapKey;
+        this.providerMultimapKey = providerMultimapKey;
+        this.entrySetKey = entrySetKey;
+      }
+
+      @Override public void configure(Binder binder) {
+        ImmutableSet<Dependency<?>> dependencies
+            = ImmutableSet.<Dependency<?>>of(Dependency.get(entrySetKey));
+
+        Provider<Set<Entry<K, Provider<V>>>> entrySetProvider =
+            binder.getProvider(entrySetKey);
+        // Binds a Map<K, Set<Provider<V>>> from a collection of Map<Entry<K, Provider<V>> if
+        // permitDuplicates was called.
+        binder.bind(providerMultimapKey).toProvider(
+            new RealProviderMultimapProvider(dependencies, entrySetProvider));
+
+        Provider<Map<K, Set<Provider<V>>>> multimapProvider =
+            binder.getProvider(providerMultimapKey);
+        binder.bind(multimapKey).toProvider(
+            new RealMultimapProvider(dependencies, multimapProvider));
+      }
+
+      @Override public int hashCode() {
+        return multimapKey.hashCode();
+      }
+
+      @Override public boolean equals(Object o) {
+        return o instanceof MultimapBinder
+            && ((MultimapBinder<?, ?>) o).multimapKey.equals(multimapKey);
+      }
+
+      final class RealProviderMultimapProvider
+          extends RealMapBinderProviderWithDependencies<Map<K, Set<Provider<V>>>> {
+        private final ImmutableSet<Dependency<?>> dependencies;
+        private final Provider<Set<Entry<K, Provider<V>>>> entrySetProvider;
+        private Map<K, Set<Provider<V>>> providerMultimap;
+
+        private RealProviderMultimapProvider(ImmutableSet<Dependency<?>> dependencies,
+            Provider<Set<Entry<K, Provider<V>>>> entrySetProvider) {
+          super(multimapKey);
+          this.dependencies = dependencies;
+          this.entrySetProvider = entrySetProvider;
+        }
+
+        @SuppressWarnings("unused")
+        @Inject void initialize(Injector injector) {
+          Map<K, ImmutableSet.Builder<Provider<V>>> providerMultimapMutable =
+              new LinkedHashMap<K, ImmutableSet.Builder<Provider<V>>>();
+          for (Entry<K, Provider<V>> entry : entrySetProvider.get()) {
+            if (!providerMultimapMutable.containsKey(entry.getKey())) {
+              providerMultimapMutable.put(
+                  entry.getKey(), ImmutableSet.<Provider<V>>builder());
+            }
+            providerMultimapMutable.get(entry.getKey()).add(entry.getValue());
+          }
+
+          ImmutableMap.Builder<K, Set<Provider<V>>> providerMultimapBuilder =
+              ImmutableMap.builder();
+          for (Entry<K, ImmutableSet.Builder<Provider<V>>> entry
+              : providerMultimapMutable.entrySet()) {
+            providerMultimapBuilder.put(entry.getKey(), entry.getValue().build());
+          }
+          providerMultimap = providerMultimapBuilder.build();
+        }
+
+        @Override public Map<K, Set<Provider<V>>> get() {
+          return providerMultimap;
+        }
+
+        @Override public Set<Dependency<?>> getDependencies() {
+          return dependencies;
+        }
+      }
+
+      final class RealMultimapProvider
+          extends RealMapBinderProviderWithDependencies<Map<K, Set<V>>> {
+        private final ImmutableSet<Dependency<?>> dependencies;
+        private final Provider<Map<K, Set<Provider<V>>>> multimapProvider;
+
+        RealMultimapProvider(
+            ImmutableSet<Dependency<?>> dependencies,
+            Provider<Map<K, Set<Provider<V>>>> multimapProvider) {
+          super(multimapKey);
+          this.dependencies = dependencies;
+          this.multimapProvider = multimapProvider;
+        }
+
+        @Override public Map<K, Set<V>> get() {
+          ImmutableMap.Builder<K, Set<V>> multimapBuilder = ImmutableMap.builder();
+          for (Entry<K, Set<Provider<V>>> entry : multimapProvider.get().entrySet()) {
+            K key = entry.getKey();
+            ImmutableSet.Builder<V> valuesBuilder = ImmutableSet.builder();
+            for (Provider<V> valueProvider : entry.getValue()) {
+              V value = valueProvider.get();
+              checkConfiguration(value != null,
+                  "Multimap injection failed due to null value for key \"%s\"", key);
+              valuesBuilder.add(value);
+            }
+            multimapBuilder.put(key, valuesBuilder.build());
+          }
+          return multimapBuilder.build();
+        }
+
+        @Override public Set<Dependency<?>> getDependencies() {
+          return dependencies;
+        }
+      }
+    }
+
+    static final class ValueProvider<V> implements Provider<V> {
+      private final Provider<V> delegate;
+      private final Binding<V> binding;
+
+      ValueProvider(Provider<V> delegate, Binding<V> binding) {
+        this.delegate = delegate;
+        this.binding = binding;
+      }
+
+      @Override public V get() {
+        return delegate.get();
+      }
+
+      public Binding<V> getValueBinding() {
+        return binding;
+      }
+    }
+
+    /**
+     * A Provider that Map.Entry that is also a Provider.  The key is the entry in the
+     * map this corresponds to and the value is the provider of the user's binding.
+     * This returns itself as the Provider.get value.
+     */
+    static final class ProviderMapEntry<K, V> implements
+        ProviderWithDependencies<Map.Entry<K, Provider<V>>>, Map.Entry<K, Provider<V>> {
+      private final K key;
+      private final Provider<V> provider;
+      private final Key<V> valueKey;
+
+      private ProviderMapEntry(K key, Provider<V> provider, Key<V> valueKey) {
+        this.key = key;
+        this.provider = provider;
+        this.valueKey = valueKey;
+      }
+
+      @Override public Entry<K, Provider<V>> get() {
+        return this;
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        return ((HasDependencies) provider).getDependencies();
+      }
+
+      public Key<V> getValueKey() {
+        return valueKey;
+      }
+
+      @Override public K getKey() {
+        return key;
+      }
+
+      @Override public Provider<V> getValue() {
+        return provider;
+      }
+
+      @Override public Provider<V> setValue(Provider<V> value) {
+        throw new UnsupportedOperationException();
+      }
+
+       @Override public boolean equals(Object obj) {
+         if (obj instanceof Map.Entry) {
+           Map.Entry o = (Map.Entry)obj;
+           return Objects.equal(key, o.getKey())
+               && Objects.equal(provider, o.getValue());
+         }
+         return false;
+      }
+
+      @Override public int hashCode() {
+        return key.hashCode() ^ provider.hashCode();
+      }
+
+      @Override public String toString() {
+        return "ProviderMapEntry(" + key + ", " + provider + ")";
+      }
+    }
+
+    private static abstract class RealMapWithExtensionProvider<T>
+        extends RealMapBinderProviderWithDependencies<T>
+        implements ProviderWithExtensionVisitor<T>, MapBinderBinding<T> {
+      public RealMapWithExtensionProvider(Object equality) {
+        super(equality);
+      }
+    }
+
+    /**
+     * A base class for ProviderWithDependencies that need equality
+     * based on a specific object.
+     */
+    private static abstract class RealMapBinderProviderWithDependencies<T> implements ProviderWithDependencies<T> {
+      private final Object equality;
+
+      public RealMapBinderProviderWithDependencies(Object equality) {
+        this.equality = equality;
+      }
+
+      @Override
+      public boolean equals(Object obj) {
+        return this.getClass() == obj.getClass() &&
+          equality.equals(((RealMapBinderProviderWithDependencies<?>)obj).equality);
+      }
+
+      @Override
+      public int hashCode() {
+        return equality.hashCode();
+      }
+    }
+
+    private Multimap<K, String> newLinkedKeyArrayValueMultimap() {
+      return Multimaps.newListMultimap(
+          new LinkedHashMap<K, Collection<String>>(),
+          new Supplier<List<String>>() {
+            @Override public List<String> get() {
+              return Lists.newArrayList();
+            }
+          });
+    }
+  }
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MapBinderBinding.java b/extensions/multibindings/src/com/google/inject/multibindings/MapBinderBinding.java
new file mode 100644
index 0000000..46d303c
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MapBinderBinding.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2010 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.inject.multibindings;
+
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A binding for a MapBinder.
+ * <p>
+ * Although MapBinders may be injected through a variety of generic types (Map&lt;K, V>, Map
+ * &lt;K, Provider&lt;V>>, Map&lt;K, Set&lt;V>>, Map<K, Set&lt;
+ * Provider&lt;V>>, and even Set&lt;Map.Entry&lt;K, Provider&lt;V>>), a
+ * MapBinderBinding exists only on the Binding associated with the Map&lt;K, V> key. Other
+ * bindings can be validated to be derived from this MapBinderBinding using
+ * {@link #containsElement(Element)}.
+ * 
+ * @param <T> The fully qualified type of the map, including Map. For example:
+ *          <code>MapBinderBinding&lt;Map&lt;String, Snack>></code>
+ * 
+ * @since 3.0
+ * @author sameb@google.com (Sam Berlin)
+ */
+public interface MapBinderBinding<T> {
+
+  /** Returns the {@link Key} for the map. */
+  Key<T> getMapKey();
+
+  /**
+   * Returns the TypeLiteral describing the keys of the map.
+   * <p>
+   * The TypeLiteral will always match the type Map's generic type. For example, if getMapKey
+   * returns a key of <code>Map&lt;String, Snack></code>, then this will always return a
+   * <code>TypeLiteral&lt;String></code>.
+   */
+  TypeLiteral<?> getKeyTypeLiteral();
+
+  /**
+   * Returns the TypeLiteral describing the values of the map.
+   * <p>
+   * The TypeLiteral will always match the type Map's generic type. For example, if getMapKey
+   * returns a key of <code>Map&lt;String, Snack></code>, then this will always return a
+   * <code>TypeLiteral&lt;Snack></code>.
+   */
+  TypeLiteral<?> getValueTypeLiteral();
+
+  /**
+   * Returns all entries in the Map. The returned list of Map.Entries contains the key and a binding
+   * to the value. Duplicate keys or values will exist as separate Map.Entries in the returned list.
+   * This is only supported on bindings returned from an injector. This will throw
+   * {@link UnsupportedOperationException} if it is called on an element retrieved from
+   * {@link Elements#getElements}.
+   * <p>
+   * The elements will always match the type Map's generic type. For example, if getMapKey returns a
+   * key of <code>Map&lt;String, Snack></code>, then this will always return a list of type
+   * <code>List&lt;Map.Entry&lt;String, Binding&lt;Snack>>></code>.
+   */
+  List<Map.Entry<?, Binding<?>>> getEntries();
+
+  /**
+   * Returns true if the MapBinder permits duplicates. This is only supported on bindings returned
+   * from an injector. This will throw {@link UnsupportedOperationException} if it is called on a
+   * MapBinderBinding retrieved from {@link Elements#getElements}.
+   */
+  boolean permitsDuplicates();
+
+  /**
+   * Returns true if this MapBinder contains the given Element in order to build the map or uses the
+   * given Element in order to support building and injecting the map. This will work for
+   * MapBinderBindings retrieved from an injector and {@link Elements#getElements}. Usually this is
+   * only necessary if you are working with elements retrieved from modules (without an Injector),
+   * otherwise {@link #getEntries} and {@link #permitsDuplicates} are better options.
+   * <p>
+   * If you need to introspect the details of the map, such as the keys, values or if it permits
+   * duplicates, it is necessary to pass the elements through an Injector and use
+   * {@link #getEntries()} and {@link #permitsDuplicates()}.
+   */
+  boolean containsElement(Element element);
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MapKey.java b/extensions/multibindings/src/com/google/inject/multibindings/MapKey.java
new file mode 100644
index 0000000..830f329
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MapKey.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2015 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.inject.multibindings;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Allows users define customized key type annotations for map bindings by annotating an annotation
+ * of a {@code Map}'s key type. The custom key annotation can be applied to methods also annotated
+ * with {@literal @}{@link ProvidesIntoMap}.
+ * 
+ * <p>A {@link StringMapKey} and {@link ClassMapKey} are provided for convenience with maps whose
+ * keys are strings or classes. For maps with enums or primitive types as keys, you must provide
+ * your own MapKey annotation, such as this one for an enum:
+ *
+ * <pre>
+ * {@literal @}MapKey(unwrapValue = true)
+ * {@literal @}Retention(RUNTIME)
+ * public {@literal @}interface MyCustomEnumKey {
+ *   MyCustomEnum value();
+ * }
+ * </pre>
+ *
+ * You can also use the whole annotation as the key, if {@code unwrapValue=false}.
+ * When unwrapValue is false, the annotation type will be the key type for the injected map and
+ * the annotation instances will be the key values. If {@code unwrapValue=true}, the value() type
+ * will be the key type for injected map and the value() instances will be the keys values.
+ *
+ * @since 4.0
+ */
+@Documented
+@Target(ANNOTATION_TYPE)
+@Retention(RUNTIME)
+public @interface MapKey {
+  /**
+   * if {@code unwrapValue} is false, then the whole annotation will be the type and annotation
+   * instances will be the keys. If {@code unwrapValue} is true, the value() type of key type
+   * annotation will be the key type for injected map and the value instances will be the keys.
+   */
+  boolean unwrapValue() default true;
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
new file mode 100644
index 0000000..f3fd552
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
@@ -0,0 +1,576 @@
+/**
+ * Copyright (C) 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.inject.multibindings;
+
+import static com.google.common.base.Predicates.equalTo;
+import static com.google.common.primitives.Ints.MAX_POWER_OF_TWO;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.inject.multibindings.Element.Type.MULTIBINDER;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.ConfigurationException;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.internal.Errors;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithDependencies;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+import com.google.inject.spi.Toolable;
+import com.google.inject.util.Types;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An API to bind multiple values separately, only to later inject them as a
+ * complete collection. Multibinder is intended for use in your application's
+ * module:
+ * <pre><code>
+ * public class SnacksModule extends AbstractModule {
+ *   protected void configure() {
+ *     Multibinder&lt;Snack&gt; multibinder
+ *         = Multibinder.newSetBinder(binder(), Snack.class);
+ *     multibinder.addBinding().toInstance(new Twix());
+ *     multibinder.addBinding().toProvider(SnickersProvider.class);
+ *     multibinder.addBinding().to(Skittles.class);
+ *   }
+ * }</code></pre>
+ *
+ * <p>With this binding, a {@link Set}{@code <Snack>} can now be injected:
+ * <pre><code>
+ * class SnackMachine {
+ *   {@literal @}Inject
+ *   public SnackMachine(Set&lt;Snack&gt; snacks) { ... }
+ * }</code></pre>
+ *
+ * If desired, {@link Collection}{@code <Provider<Snack>>} can also be injected.
+ *
+ * <p>Contributing multibindings from different modules is supported. For
+ * example, it is okay for both {@code CandyModule} and {@code ChipsModule}
+ * to create their own {@code Multibinder<Snack>}, and to each contribute
+ * bindings to the set of snacks. When that set is injected, it will contain
+ * elements from both modules.
+ *
+ * <p>The set's iteration order is consistent with the binding order. This is
+ * convenient when multiple elements are contributed by the same module because
+ * that module can order its bindings appropriately. Avoid relying on the
+ * iteration order of elements contributed by different modules, since there is
+ * no equivalent mechanism to order modules.
+ *
+ * <p>The set is unmodifiable.  Elements can only be added to the set by
+ * configuring the multibinder.  Elements can never be removed from the set.
+ *
+ * <p>Elements are resolved at set injection time. If an element is bound to a
+ * provider, that provider's get method will be called each time the set is
+ * injected (unless the binding is also scoped).
+ *
+ * <p>Annotations are be used to create different sets of the same element
+ * type. Each distinct annotation gets its own independent collection of
+ * elements.
+ *
+ * <p><strong>Elements must be distinct.</strong> If multiple bound elements
+ * have the same value, set injection will fail.
+ *
+ * <p><strong>Elements must be non-null.</strong> If any set element is null,
+ * set injection will fail.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public abstract class Multibinder<T> {
+  private Multibinder() {}
+
+  /**
+   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+   * itself bound with no binding annotation.
+   */
+  public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type) {
+    return newRealSetBinder(binder, Key.get(type));
+  }
+
+  /**
+   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+   * itself bound with no binding annotation.
+   */
+  public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type) {
+    return newRealSetBinder(binder, Key.get(type));
+  }
+
+  /**
+   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+   * itself bound with {@code annotation}.
+   */
+  public static <T> Multibinder<T> newSetBinder(
+      Binder binder, TypeLiteral<T> type, Annotation annotation) {
+    return newRealSetBinder(binder, Key.get(type, annotation));
+  }
+
+  /**
+   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+   * itself bound with {@code annotation}.
+   */
+  public static <T> Multibinder<T> newSetBinder(
+      Binder binder, Class<T> type, Annotation annotation) {
+    return newRealSetBinder(binder, Key.get(type, annotation));
+  }
+
+  /**
+   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+   * itself bound with {@code annotationType}.
+   */
+  public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type,
+      Class<? extends Annotation> annotationType) {
+    return newRealSetBinder(binder, Key.get(type, annotationType));
+  }
+
+  /**
+   * Returns a new multibinder that collects instances of the key's type in a {@link Set} that is
+   * itself bound with the annotation (if any) of the key.
+   *
+   * @since 4.0
+   */
+  public static <T> Multibinder<T> newSetBinder(Binder binder, Key<T> key) {
+    return newRealSetBinder(binder, key);
+  }
+
+  /**
+   * Implementation of newSetBinder.
+   */
+  static <T> RealMultibinder<T> newRealSetBinder(Binder binder, Key<T> key) {
+    binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
+    RealMultibinder<T> result = new RealMultibinder<T>(binder, key.getTypeLiteral(),
+        key.ofType(setOf(key.getTypeLiteral())));
+    binder.install(result);
+    return result;
+  }
+
+  /**
+   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+   * itself bound with {@code annotationType}.
+   */
+  public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type,
+      Class<? extends Annotation> annotationType) {
+    return newSetBinder(binder, Key.get(type, annotationType));
+  }
+
+  @SuppressWarnings("unchecked") // wrapping a T in a Set safely returns a Set<T>
+  static <T> TypeLiteral<Set<T>> setOf(TypeLiteral<T> elementType) {
+    Type type = Types.setOf(elementType.getType());
+    return (TypeLiteral<Set<T>>) TypeLiteral.get(type);
+  }
+
+  @SuppressWarnings("unchecked")
+  static <T> TypeLiteral<Collection<Provider<T>>> collectionOfProvidersOf(
+      TypeLiteral<T> elementType) {
+    Type providerType = Types.providerOf(elementType.getType());
+    Type type = Types.newParameterizedType(Collection.class, providerType);
+    return (TypeLiteral<Collection<Provider<T>>>) TypeLiteral.get(type);
+  }
+
+  @SuppressWarnings("unchecked")
+  static <T> TypeLiteral<Collection<javax.inject.Provider<T>>> collectionOfJavaxProvidersOf(
+      TypeLiteral<T> elementType) {
+    Type providerType =
+        Types.newParameterizedType(javax.inject.Provider.class, elementType.getType());
+    Type type = Types.newParameterizedType(Collection.class, providerType);
+    return (TypeLiteral<Collection<javax.inject.Provider<T>>>) TypeLiteral.get(type);
+  }
+
+  /**
+   * Configures the bound set to silently discard duplicate elements. When multiple equal values are
+   * bound, the one that gets included is arbitrary. When multiple modules contribute elements to
+   * the set, this configuration option impacts all of them.
+   *
+   * @return this multibinder
+   * @since 3.0
+   */
+  public abstract Multibinder<T> permitDuplicates();
+
+  /**
+   * Returns a binding builder used to add a new element in the set. Each
+   * bound element must have a distinct value. Bound providers will be
+   * evaluated each time the set is injected.
+   *
+   * <p>It is an error to call this method without also calling one of the
+   * {@code to} methods on the returned binding builder.
+   *
+   * <p>Scoping elements independently is supported. Use the {@code in} method
+   * to specify a binding scope.
+   */
+  public abstract LinkedBindingBuilder<T> addBinding();
+
+  /**
+   * The actual multibinder plays several roles:
+   *
+   * <p>As a Multibinder, it acts as a factory for LinkedBindingBuilders for
+   * each of the set's elements. Each binding is given an annotation that
+   * identifies it as a part of this set.
+   *
+   * <p>As a Module, it installs the binding to the set itself. As a module,
+   * this implements equals() and hashcode() in order to trick Guice into
+   * executing its configure() method only once. That makes it so that
+   * multiple multibinders can be created for the same target collection, but
+   * only one is bound. Since the list of bindings is retrieved from the
+   * injector itself (and not the multibinder), each multibinder has access to
+   * all contributions from all multibinders.
+   *
+   * <p>As a Provider, this constructs the set instances.
+   *
+   * <p>We use a subclass to hide 'implements Module, Provider' from the public
+   * API.
+   */
+  static final class RealMultibinder<T> extends Multibinder<T>
+      implements Module, ProviderWithExtensionVisitor<Set<T>>, HasDependencies,
+          MultibinderBinding<Set<T>> {
+
+    private final TypeLiteral<T> elementType;
+    private final String setName;
+    private final Key<Set<T>> setKey;
+    private final Key<Collection<Provider<T>>> collectionOfProvidersKey;
+    private final Key<Collection<javax.inject.Provider<T>>> collectionOfJavaxProvidersKey;
+    private final Key<Boolean> permitDuplicatesKey;
+
+    /* the target injector's binder. non-null until initialization, null afterwards */
+    private Binder binder;
+
+    /* a binding for each element in the set. null until initialization, non-null afterwards */
+    private ImmutableList<Binding<T>> bindings;
+    private Set<Dependency<?>> dependencies;
+
+    /** whether duplicates are allowed. Possibly configured by a different instance */
+    private boolean permitDuplicates;
+
+    private RealMultibinder(Binder binder, TypeLiteral<T> elementType, Key<Set<T>> setKey) {
+      this.binder = checkNotNull(binder, "binder");
+      this.elementType = checkNotNull(elementType, "elementType");
+      this.setKey = checkNotNull(setKey, "setKey");
+      this.collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType));
+      this.collectionOfJavaxProvidersKey = setKey.ofType(collectionOfJavaxProvidersOf(elementType));
+      this.setName = RealElement.nameOf(setKey);
+      this.permitDuplicatesKey = Key.get(Boolean.class, named(toString() + " permits duplicates"));
+    }
+
+    public void configure(Binder binder) {
+      checkConfiguration(!isInitialized(), "Multibinder was already initialized");
+
+      binder.bind(setKey).toProvider(this);
+      binder.bind(collectionOfProvidersKey).toProvider(
+          new RealMultibinderCollectionOfProvidersProvider());
+
+      // The collection this exposes is internally an ImmutableList, so it's OK to massage
+      // the guice Provider to javax Provider in the value (since the guice Provider implements
+      // javax Provider).
+      @SuppressWarnings("unchecked")
+      Key key = (Key) collectionOfProvidersKey;
+      binder.bind(collectionOfJavaxProvidersKey).to(key);
+    }
+
+    @Override public Multibinder<T> permitDuplicates() {
+      binder.install(new PermitDuplicatesModule(permitDuplicatesKey));
+      return this;
+    }
+    
+    Key<T> getKeyForNewItem() {
+      checkConfiguration(!isInitialized(), "Multibinder was already initialized");
+      return Key.get(elementType, new RealElement(setName, MULTIBINDER, ""));
+    }
+
+    @Override public LinkedBindingBuilder<T> addBinding() {
+      return binder.bind(getKeyForNewItem());
+    }
+
+    /**
+     * Invoked by Guice at Injector-creation time to prepare providers for each
+     * element in this set. At this time the set's size is known, but its
+     * contents are only evaluated when get() is invoked.
+     */
+    @Toolable @Inject void initialize(Injector injector) {
+      List<Binding<T>> bindings = Lists.newArrayList();
+      Set<Indexer.IndexedBinding> index = Sets.newHashSet();
+      Indexer indexer = new Indexer(injector);
+      List<Dependency<?>> dependencies = Lists.newArrayList();
+      for (Binding<?> entry : injector.findBindingsByType(elementType)) {
+        if (keyMatches(entry.getKey())) {
+          @SuppressWarnings("unchecked") // protected by findBindingsByType()
+          Binding<T> binding = (Binding<T>) entry;
+          if (index.add(binding.acceptTargetVisitor(indexer))) {
+            bindings.add(binding);
+            dependencies.add(Dependency.get(binding.getKey()));
+          }
+        }
+      }
+
+      this.bindings = ImmutableList.copyOf(bindings);
+      this.dependencies = ImmutableSet.copyOf(dependencies);
+      this.permitDuplicates = permitsDuplicates(injector);
+      this.binder = null;
+    }
+
+    // This is forked from com.google.common.collect.Maps.capacity 
+    private static int mapCapacity(int numBindings) {
+      if (numBindings < 3) {
+        return numBindings + 1;
+      } else  if (numBindings < MAX_POWER_OF_TWO) {
+        return (int) (numBindings / 0.75F + 1.0F);
+      }
+      return Integer.MAX_VALUE;
+    }
+
+    boolean permitsDuplicates(Injector injector) {
+      return injector.getBindings().containsKey(permitDuplicatesKey);
+    }
+
+    private boolean keyMatches(Key<?> key) {
+      return key.getTypeLiteral().equals(elementType)
+          && key.getAnnotation() instanceof Element
+          && ((Element) key.getAnnotation()).setName().equals(setName)
+          && ((Element) key.getAnnotation()).type() == MULTIBINDER;
+    }
+
+    private boolean isInitialized() {
+      return binder == null;
+    }
+
+    public Set<T> get() {
+      checkConfiguration(isInitialized(), "Multibinder is not initialized");
+
+      Map<T, Binding<T>> result = new LinkedHashMap<T, Binding<T>>(mapCapacity(bindings.size()));
+      for (Binding<T> binding : bindings) {
+        final T newValue = binding.getProvider().get();
+        checkConfiguration(newValue != null,
+            "Set injection failed due to null element bound at: %s",
+            binding.getSource());
+        Binding<T> duplicateBinding = result.put(newValue, binding);
+        if (!permitDuplicates && duplicateBinding != null) {
+          throw newDuplicateValuesException(result, binding, newValue, duplicateBinding);
+        }
+      }
+      return ImmutableSet.copyOf(result.keySet());
+    }
+
+    @SuppressWarnings("unchecked")
+    public <B, V> V acceptExtensionVisitor(
+        BindingTargetVisitor<B, V> visitor,
+        ProviderInstanceBinding<? extends B> binding) {
+      if (visitor instanceof MultibindingsTargetVisitor) {
+        return ((MultibindingsTargetVisitor<Set<T>, V>) visitor).visit(this);
+      } else {
+        return visitor.visit(binding);
+      }
+    }
+
+    String getSetName() {
+      return setName;
+    }
+
+    public TypeLiteral<?> getElementTypeLiteral() {
+      return elementType;
+    }
+
+    public Key<Set<T>> getSetKey() {
+      return setKey;
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<Binding<?>> getElements() {
+      if (isInitialized()) {
+        return (List<Binding<?>>) (List<?>) bindings; // safe because bindings is immutable.
+      } else {
+        throw new UnsupportedOperationException("getElements() not supported for module bindings");
+      }
+    }
+
+    public boolean permitsDuplicates() {
+      if (isInitialized()) {
+        return permitDuplicates;
+      } else {
+        throw new UnsupportedOperationException(
+            "permitsDuplicates() not supported for module bindings");
+      }
+    }
+
+    public boolean containsElement(com.google.inject.spi.Element element) {
+      if (element instanceof Binding) {
+        Binding<?> binding = (Binding<?>) element;
+        return keyMatches(binding.getKey())
+            || binding.getKey().equals(permitDuplicatesKey)
+            || binding.getKey().equals(setKey)
+            || binding.getKey().equals(collectionOfProvidersKey)
+            || binding.getKey().equals(collectionOfJavaxProvidersKey);
+      } else {
+        return false;
+      }
+    }
+
+    public Set<Dependency<?>> getDependencies() {
+      if (!isInitialized()) {
+        return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
+      } else {
+        return dependencies;
+      }
+    }
+
+    @Override public boolean equals(Object o) {
+      return o instanceof RealMultibinder
+          && ((RealMultibinder<?>) o).setKey.equals(setKey);
+    }
+
+    @Override public int hashCode() {
+      return setKey.hashCode();
+    }
+
+    @Override public String toString() {
+      return (setName.isEmpty() ? "" : setName + " ") + "Multibinder<" + elementType + ">";
+    }
+
+    final class RealMultibinderCollectionOfProvidersProvider
+        implements ProviderWithDependencies<Collection<Provider<T>>> {
+      @Override public Collection<Provider<T>> get() {
+        checkConfiguration(isInitialized(), "Multibinder is not initialized");
+        int size = bindings.size();
+        @SuppressWarnings("unchecked")  // safe because we only put Provider<T> into it.
+        Provider<T>[] providers = new Provider[size];
+        for (int i = 0; i < size; i++) {
+          providers[i] = bindings.get(i).getProvider();
+        }
+        return ImmutableList.copyOf(providers);
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        if (!isInitialized()) {
+          return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
+        }
+        ImmutableSet.Builder<Dependency<?>> setBuilder = ImmutableSet.builder();
+        for (Dependency<?> dependency : dependencies) {
+          Key key = dependency.getKey();
+          setBuilder.add(
+              Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType()))));
+        }
+        return setBuilder.build();
+      }
+
+      Key getCollectionKey() {
+        return RealMultibinder.this.collectionOfProvidersKey;
+      }
+
+      @Override public boolean equals(Object o) {
+        return o instanceof Multibinder.RealMultibinder.RealMultibinderCollectionOfProvidersProvider
+            && ((Multibinder.RealMultibinder.RealMultibinderCollectionOfProvidersProvider) o)
+                .getCollectionKey().equals(getCollectionKey());
+      }
+
+      @Override public int hashCode() {
+        return getCollectionKey().hashCode();
+      }
+    }
+  }
+
+  /**
+   * We install the permit duplicates configuration as its own binding, all by itself. This way,
+   * if only one of a multibinder's users remember to call permitDuplicates(), they're still
+   * permitted.
+   */
+  private static class PermitDuplicatesModule extends AbstractModule {
+    private final Key<Boolean> key;
+
+    PermitDuplicatesModule(Key<Boolean> key) {
+      this.key = key;
+    }
+
+    @Override protected void configure() {
+      bind(key).toInstance(true);
+    }
+
+    @Override public boolean equals(Object o) {
+      return o instanceof PermitDuplicatesModule
+          && ((PermitDuplicatesModule) o).key.equals(key);
+    }
+
+    @Override public int hashCode() {
+      return getClass().hashCode() ^ key.hashCode();
+    }
+  }
+
+  static void checkConfiguration(boolean condition, String format, Object... args) {
+    if (condition) {
+      return;
+    }
+
+    throw new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args))));
+  }
+
+  private static <T> ConfigurationException newDuplicateValuesException(
+      Map<T, Binding<T>> existingBindings,
+      Binding<T> binding,
+      final T newValue,
+      Binding<T> duplicateBinding) {
+    T oldValue = getOnlyElement(filter(existingBindings.keySet(), equalTo(newValue)));
+    String oldString = oldValue.toString();
+    String newString = newValue.toString();
+    if (Objects.equal(oldString, newString)) {
+      // When the value strings match, just show the source of the bindings
+      return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(
+          "Set injection failed due to duplicated element \"%s\""
+              + "\n    Bound at %s\n    Bound at %s",
+          newValue,
+          duplicateBinding.getSource(),
+          binding.getSource()))));
+    } else {
+      // When the value strings don't match, include them both as they may be useful for debugging
+      return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(
+          "Set injection failed due to multiple elements comparing equal:"
+              + "\n    \"%s\"\n        bound at %s"
+              + "\n    \"%s\"\n        bound at %s",
+          oldValue,
+          duplicateBinding.getSource(),
+          newValue,
+          binding.getSource()))));
+    }
+  }
+
+  static <T> T checkNotNull(T reference, String name) {
+    if (reference != null) {
+      return reference;
+    }
+
+    NullPointerException npe = new NullPointerException(name);
+    throw new ConfigurationException(ImmutableSet.of(
+        new Message(npe.toString(), npe)));
+  }
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MultibinderBinding.java b/extensions/multibindings/src/com/google/inject/multibindings/MultibinderBinding.java
new file mode 100644
index 0000000..998452c
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MultibinderBinding.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (C) 2010 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.inject.multibindings;
+
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+
+import java.util.List;
+
+/**
+ * A binding for a Multibinder.
+ * 
+ * @param <T> The fully qualified type of the set, including Set. For example:
+ *          <code>MultibinderBinding&lt;Set&lt;Boolean>></code>
+ * 
+ * @since 3.0
+ * @author sameb@google.com (Sam Berlin)
+ */
+public interface MultibinderBinding<T> {
+
+  /** Returns the key for the set. */
+  Key<T> getSetKey();
+  
+  /**
+   * Returns the TypeLiteral that describes the type of elements in the set.
+   * <p>
+   * The elements will always match the type Set's generic type. For example, if getSetKey returns a
+   * key of <code>Set&lt;String></code>, then this will always return a
+   * <code>TypeLiteral&lt;String></code>.
+   */
+  TypeLiteral<?> getElementTypeLiteral();
+
+  /**
+   * Returns all bindings that make up the set. This is only supported on bindings returned from an
+   * injector. This will throw {@link UnsupportedOperationException} if it is called on an element
+   * retrieved from {@link Elements#getElements}.
+   * <p>
+   * The elements will always match the type Set's generic type. For example, if getSetKey returns a
+   * key of <code>Set&lt;String></code>, then this will always return a list of type
+   * <code>List&lt;Binding&lt;String>></code>.
+   */
+  List<Binding<?>> getElements();
+
+  /**
+   * Returns true if the multibinder permits duplicates. This is only supported on bindings returned
+   * from an injector. This will throw {@link UnsupportedOperationException} if it is called on a
+   * MultibinderBinding retrieved from {@link Elements#getElements}.
+   */
+  boolean permitsDuplicates();
+
+  /**
+   * Returns true if this Multibinder uses the given Element. This will be true for bindings that
+   * derive the elements of the set and other bindings that Multibinder uses internally. This will
+   * work for MultibinderBindings retrieved from an injector and {@link Elements#getElements}.
+   * Usually this is only necessary if you are working with elements retrieved from modules (without
+   * an Injector), otherwise {@link #getElements} and {@link #permitsDuplicates} are better options.
+   * <p>
+   * If you need to introspect the details of the set, such as the values or if it permits
+   * duplicates, it is necessary to pass the elements through an Injector and use
+   * {@link #getElements()} and {@link #permitsDuplicates()}.
+   */
+  boolean containsElement(Element element);
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsScanner.java b/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsScanner.java
new file mode 100644
index 0000000..95b4d5f
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsScanner.java
@@ -0,0 +1,194 @@
+/**
+ * Copyright (C) 2015 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.inject.multibindings;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ModuleAnnotatedMethodScanner;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Scans a module for annotations that signal multibindings, mapbindings, and optional bindings.
+ *
+ * @since 4.0
+ */
+public class MultibindingsScanner {
+
+  private MultibindingsScanner() {}
+
+  /**
+   * Returns a module that, when installed, will scan all modules for methods with the annotations
+   * {@literal @}{@link ProvidesIntoMap}, {@literal @}{@link ProvidesIntoSet}, and
+   * {@literal @}{@link ProvidesIntoOptional}.
+   * 
+   * <p>This is a convenience method, equivalent to doing
+   * {@code binder().scanModulesForAnnotatedMethods(MultibindingsScanner.scanner())}.
+   */
+  public static Module asModule() {
+    return new AbstractModule() {
+      @Override protected void configure() {
+        binder().scanModulesForAnnotatedMethods(Scanner.INSTANCE);
+      }
+    };
+  }
+  
+  /**
+   * Returns a {@link ModuleAnnotatedMethodScanner} that, when bound, will scan all modules for
+   * methods with the annotations {@literal @}{@link ProvidesIntoMap},
+   * {@literal @}{@link ProvidesIntoSet}, and {@literal @}{@link ProvidesIntoOptional}.
+   */
+  public static ModuleAnnotatedMethodScanner scanner() {
+    return Scanner.INSTANCE;
+  }
+
+  private static class Scanner extends ModuleAnnotatedMethodScanner {
+    private static final Scanner INSTANCE = new Scanner();
+    
+    @Override
+    public Set<? extends Class<? extends Annotation>> annotationClasses() {
+      return ImmutableSet.of(
+          ProvidesIntoSet.class, ProvidesIntoMap.class, ProvidesIntoOptional.class);
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"}) // mapKey doesn't know its key type
+    @Override
+    public <T> Key<T> prepareMethod(Binder binder, Annotation annotation, Key<T> key,
+        InjectionPoint injectionPoint) {
+      Method method = (Method) injectionPoint.getMember();
+      AnnotationOrError mapKey = findMapKeyAnnotation(binder, method);
+      if (annotation instanceof ProvidesIntoSet) {
+        if (mapKey.annotation != null) {
+          binder.addError("Found a MapKey annotation on non map binding at %s.", method);
+        }
+        return Multibinder.newRealSetBinder(binder, key).getKeyForNewItem();
+      } else if (annotation instanceof ProvidesIntoMap) {
+        if (mapKey.error) {
+          // Already failed on the MapKey, don't bother doing more work.
+          return key;
+        }
+        if (mapKey.annotation == null) {
+          // If no MapKey, make an error and abort.
+          binder.addError("No MapKey found for map binding at %s.", method);
+          return key;
+        }
+        TypeAndValue typeAndValue = typeAndValueOfMapKey(mapKey.annotation);
+        return MapBinder.newRealMapBinder(binder, typeAndValue.type, key)
+            .getKeyForNewValue(typeAndValue.value);
+      } else if (annotation instanceof ProvidesIntoOptional) {
+        if (mapKey.annotation != null) {
+          binder.addError("Found a MapKey annotation on non map binding at %s.", method);
+        }
+        switch (((ProvidesIntoOptional)annotation).value()) {
+          case DEFAULT:
+            return OptionalBinder.newRealOptionalBinder(binder, key).getKeyForDefaultBinding();
+          case ACTUAL:
+            return OptionalBinder.newRealOptionalBinder(binder, key).getKeyForActualBinding();
+        }
+      }
+      throw new IllegalStateException("Invalid annotation: " + annotation);
+    }
+  }
+  
+  private static class AnnotationOrError {
+    final Annotation annotation;
+    final boolean error;
+    AnnotationOrError(Annotation annotation, boolean error) {
+      this.annotation = annotation;
+      this.error = error;
+    }
+
+    static AnnotationOrError forPossiblyNullAnnotation(Annotation annotation) {
+      return new AnnotationOrError(annotation, false);
+    }
+    
+    static AnnotationOrError forError() {
+      return new AnnotationOrError(null, true);
+    }
+  }
+
+  private static AnnotationOrError findMapKeyAnnotation(Binder binder, Method method) {
+    Annotation foundAnnotation = null;
+    for (Annotation annotation : method.getAnnotations()) {
+      MapKey mapKey = annotation.annotationType().getAnnotation(MapKey.class);
+      if (mapKey != null) {
+        if (foundAnnotation != null) {
+          binder.addError("Found more than one MapKey annotations on %s.", method);
+          return AnnotationOrError.forError();
+        }
+        if (mapKey.unwrapValue()) {
+          try {
+            // validate there's a declared method called "value"
+            Method valueMethod = annotation.annotationType().getDeclaredMethod("value");
+            if (valueMethod.getReturnType().isArray()) {
+              binder.addError("Array types are not allowed in a MapKey with unwrapValue=true: %s",                    
+                  annotation.annotationType());
+              return AnnotationOrError.forError();
+            }
+          } catch (NoSuchMethodException invalid) {
+            binder.addError("No 'value' method in MapKey with unwrapValue=true: %s",
+                annotation.annotationType());
+            return AnnotationOrError.forError();
+          }
+        }
+        foundAnnotation = annotation;
+      }
+    }
+    return AnnotationOrError.forPossiblyNullAnnotation(foundAnnotation);
+  }
+
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  static TypeAndValue<?> typeAndValueOfMapKey(Annotation mapKeyAnnotation) {
+    if (!mapKeyAnnotation.annotationType().getAnnotation(MapKey.class).unwrapValue()) {
+      return new TypeAndValue(TypeLiteral.get(mapKeyAnnotation.annotationType()), mapKeyAnnotation);
+    } else {
+      try {
+        Method valueMethod = mapKeyAnnotation.annotationType().getDeclaredMethod("value");
+        valueMethod.setAccessible(true);
+        TypeLiteral<?> returnType =
+            TypeLiteral.get(mapKeyAnnotation.annotationType()).getReturnType(valueMethod);
+        return new TypeAndValue(returnType, valueMethod.invoke(mapKeyAnnotation));
+      } catch (NoSuchMethodException e) {
+        throw new IllegalStateException(e);
+      } catch (SecurityException e) {
+        throw new IllegalStateException(e);
+      } catch (IllegalAccessException e) {
+        throw new IllegalStateException(e);
+      } catch (InvocationTargetException e) {
+        throw new IllegalStateException(e);
+      }
+    }
+  }
+
+  private static class TypeAndValue<T> {
+    final TypeLiteral<T> type;
+    final T value;
+
+    TypeAndValue(TypeLiteral<T> type, T value) {
+      this.type = type;
+      this.value = value;
+    }
+  }
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java b/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java
new file mode 100644
index 0000000..9378e19
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2010 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.inject.multibindings;
+
+import com.google.inject.spi.BindingTargetVisitor;
+
+/**
+ * A visitor for the multibinder extension.
+ * <p>
+ * If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ * {@link Multibinder}, {@link MapBinder} or {@link OptionalBinderBinding} will be visited through
+ * this interface.
+ *
+ * @since 3.0
+ * @author sameb@google.com (Sam Berlin)
+ */
+public interface MultibindingsTargetVisitor<T, V> extends BindingTargetVisitor<T, V> {
+  
+  /**
+   * Visits a binding created through {@link Multibinder}.
+   */
+  V visit(MultibinderBinding<? extends T> multibinding);
+  
+  /**
+   * Visits a binding created through {@link MapBinder}.
+   */
+  V visit(MapBinderBinding<? extends T> mapbinding);
+  
+  /**
+   * Visits a binding created through {@link OptionalBinder}.
+   * 
+   * @since 4.0
+   */
+  V visit(OptionalBinderBinding<? extends T> optionalbinding);
+
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java b/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java
new file mode 100644
index 0000000..1986e7c
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java
@@ -0,0 +1,754 @@
+/**
+ * Copyright (C) 2014 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.inject.multibindings;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.inject.multibindings.Multibinder.checkConfiguration;
+import static com.google.inject.util.Types.newParameterizedType;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderLookup;
+import com.google.inject.spi.ProviderWithDependencies;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+import com.google.inject.spi.Toolable;
+import com.google.inject.util.Types;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Set;
+
+import javax.inject.Qualifier;
+
+
+/**
+ * An API to bind optional values, optionally with a default value.
+ * OptionalBinder fulfills two roles: <ol>
+ * <li>It allows a framework to define an injection point that may or
+ *     may not be bound by users.
+ * <li>It allows a framework to supply a default value that can be changed
+ *     by users.
+ * </ol>
+ * 
+ * <p>When an OptionalBinder is added, it will always supply the bindings:
+ * {@code Optional<T>} and {@code Optional<Provider<T>>}.  If
+ * {@link #setBinding} or {@link #setDefault} are called, it will also
+ * bind {@code T}.
+ * 
+ * <p>{@code setDefault} is intended for use by frameworks that need a default
+ * value.  User code can call {@code setBinding} to override the default.
+ * <b>Warning: Even if setBinding is called, the default binding
+ * will still exist in the object graph.  If it is a singleton, it will be
+ * instantiated in {@code Stage.PRODUCTION}.</b>
+ * 
+ * <p>If setDefault or setBinding are linked to Providers, the Provider may return
+ * {@code null}.  If it does, the Optional bindings will be absent.  Binding
+ * setBinding to a Provider that returns null will not cause OptionalBinder
+ * to fall back to the setDefault binding.
+ * 
+ * <p>If neither setDefault nor setBinding are called, it will try to link to a
+ * user-supplied binding of the same type.  If no binding exists, the optionals
+ * will be absent.  Otherwise, if a user-supplied binding of that type exists,
+ * or if setBinding or setDefault are called, the optionals will return present
+ * if they are bound to a non-null value.
+ *
+ * <p>Values are resolved at injection time. If a value is bound to a
+ * provider, that provider's get method will be called each time the optional
+ * is injected (unless the binding is also scoped, or an optional of provider is
+ * injected).
+ * 
+ * <p>Annotations are used to create different optionals of the same key/value
+ * type. Each distinct annotation gets its own independent binding.
+ *  
+ * <pre><code>
+ * public class FrameworkModule extends AbstractModule {
+ *   protected void configure() {
+ *     OptionalBinder.newOptionalBinder(binder(), Renamer.class);
+ *   }
+ * }</code></pre>
+ *
+ * <p>With this module, an {@link Optional}{@code <Renamer>} can now be
+ * injected.  With no other bindings, the optional will be absent.
+ * Users can specify bindings in one of two ways:
+ * 
+ * <p>Option 1:
+ * <pre><code>
+ * public class UserRenamerModule extends AbstractModule {
+ *   protected void configure() {
+ *     bind(Renamer.class).to(ReplacingRenamer.class);
+ *   }
+ * }</code></pre>
+ * 
+ * <p>or Option 2:
+ * <pre><code>
+ * public class UserRenamerModule extends AbstractModule {
+ *   protected void configure() {
+ *     OptionalBinder.newOptionalBinder(binder(), Renamer.class)
+ *         .setBinding().to(ReplacingRenamer.class);
+ *   }
+ * }</code></pre>
+ * With both options, the {@code Optional<Renamer>} will be present and supply the
+ * ReplacingRenamer. 
+ * 
+ * <p>Default values can be supplied using:
+ * <pre><code>
+ * public class FrameworkModule extends AbstractModule {
+ *   protected void configure() {
+ *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
+ *         .setDefault().toInstance(DEFAULT_LOOKUP_URL);
+ *   }
+ * }</code></pre>
+ * With the above module, code can inject an {@code @LookupUrl String} and it
+ * will supply the DEFAULT_LOOKUP_URL.  A user can change this value by binding
+ * <pre><code>
+ * public class UserLookupModule extends AbstractModule {
+ *   protected void configure() {
+ *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
+ *         .setBinding().toInstance(CUSTOM_LOOKUP_URL);
+ *   }
+ * }</code></pre>
+ * ... which will override the default value.
+ * 
+ * <p>If one module uses setDefault the only way to override the default is to use setBinding.
+ * It is an error for a user to specify the binding without using OptionalBinder if
+ * setDefault or setBinding are called.  For example, 
+ * <pre><code>
+ * public class FrameworkModule extends AbstractModule {
+ *   protected void configure() {
+ *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
+ *         .setDefault().toInstance(DEFAULT_LOOKUP_URL);
+ *   }
+ * }
+ * public class UserLookupModule extends AbstractModule {
+ *   protected void configure() {
+ *     bind(Key.get(String.class, LookupUrl.class)).toInstance(CUSTOM_LOOKUP_URL);
+ *   } 
+ * }</code></pre>
+ * ... would generate an error, because both the framework and the user are trying to bind
+ * {@code @LookupUrl String}. 
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+public abstract class OptionalBinder<T> {
+
+  /* Reflectively capture java 8's Optional types so we can bind them if we're running in java8. */
+  private static final Class<?> JAVA_OPTIONAL_CLASS;
+  private static final Method JAVA_EMPTY_METHOD;
+  private static final Method JAVA_OF_NULLABLE_METHOD;
+  static {
+    Class<?> optional = null;
+    Method empty = null;
+    Method ofNullable = null;
+    boolean useJavaOptional = false;
+    try {
+      optional = Class.forName("java.util.Optional");
+      empty = optional.getDeclaredMethod("empty");
+      ofNullable = optional.getDeclaredMethod("ofNullable", Object.class);
+      useJavaOptional = true;
+    } catch (ClassNotFoundException ignored) {
+    } catch (NoSuchMethodException ignored) {
+    } catch (SecurityException ignored) {
+    }
+    JAVA_OPTIONAL_CLASS = useJavaOptional ? optional : null;
+    JAVA_EMPTY_METHOD = useJavaOptional ? empty : null;
+    JAVA_OF_NULLABLE_METHOD = useJavaOptional ? ofNullable : null;
+  }
+
+  private OptionalBinder() {}
+
+  public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Class<T> type) {
+    return newRealOptionalBinder(binder, Key.get(type));
+  }
+  
+  public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, TypeLiteral<T> type) {
+    return newRealOptionalBinder(binder, Key.get(type));
+  }
+  
+  public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Key<T> type) {
+    return newRealOptionalBinder(binder, type);
+  }
+  
+  static <T> RealOptionalBinder<T> newRealOptionalBinder(Binder binder, Key<T> type) {
+    binder = binder.skipSources(OptionalBinder.class, RealOptionalBinder.class);
+    RealOptionalBinder<T> optionalBinder = new RealOptionalBinder<T>(binder, type);
+    binder.install(optionalBinder);
+    return optionalBinder;
+  }
+
+  @SuppressWarnings("unchecked")
+  static <T> TypeLiteral<Optional<T>> optionalOf(
+      TypeLiteral<T> type) {
+    return (TypeLiteral<Optional<T>>) TypeLiteral.get(
+        Types.newParameterizedType(Optional.class,  type.getType()));
+  }
+
+  static <T> TypeLiteral<?> javaOptionalOf(
+      TypeLiteral<T> type) {
+    checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
+    return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, type.getType()));
+  }
+
+  @SuppressWarnings("unchecked")
+  static <T> TypeLiteral<Optional<javax.inject.Provider<T>>> optionalOfJavaxProvider(
+      TypeLiteral<T> type) {
+    return (TypeLiteral<Optional<javax.inject.Provider<T>>>) TypeLiteral.get(
+        Types.newParameterizedType(Optional.class,
+            newParameterizedType(javax.inject.Provider.class, type.getType())));
+  }
+
+  static <T> TypeLiteral<?> javaOptionalOfJavaxProvider(
+      TypeLiteral<T> type) {
+    checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
+    return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS,
+        newParameterizedType(javax.inject.Provider.class, type.getType())));
+  }
+
+  @SuppressWarnings("unchecked")
+  static <T> TypeLiteral<Optional<Provider<T>>> optionalOfProvider(TypeLiteral<T> type) {
+    return (TypeLiteral<Optional<Provider<T>>>) TypeLiteral.get(Types.newParameterizedType(
+        Optional.class, newParameterizedType(Provider.class, type.getType())));
+  }
+
+  static <T> TypeLiteral<?> javaOptionalOfProvider(TypeLiteral<T> type) {
+    checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
+    return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS,
+        newParameterizedType(Provider.class, type.getType())));
+  }
+
+  @SuppressWarnings("unchecked")
+  static <T> Key<Provider<T>> providerOf(Key<T> key) {
+    Type providerT = Types.providerOf(key.getTypeLiteral().getType());
+    return (Key<Provider<T>>) key.ofType(providerT);
+  }
+
+  /**
+   * Returns a binding builder used to set the default value that will be injected.
+   * The binding set by this method will be ignored if {@link #setBinding} is called.
+   * 
+   * <p>It is an error to call this method without also calling one of the {@code to}
+   * methods on the returned binding builder. 
+   */
+  public abstract LinkedBindingBuilder<T> setDefault();
+
+
+  /**
+   * Returns a binding builder used to set the actual value that will be injected.
+   * This overrides any binding set by {@link #setDefault}.
+   * 
+   * <p>It is an error to call this method without also calling one of the {@code to}
+   * methods on the returned binding builder. 
+   */
+  public abstract LinkedBindingBuilder<T> setBinding();
+  
+  enum Source { DEFAULT, ACTUAL }
+  
+  @Retention(RUNTIME)
+  @Qualifier
+  @interface Default {
+    String value();
+  }
+
+  @Retention(RUNTIME)
+  @Qualifier
+  @interface Actual {
+    String value();
+  }
+
+  /**
+   * The actual OptionalBinder plays several roles.  It implements Module to hide that
+   * fact from the public API, and installs the various bindings that are exposed to the user.
+   */
+  static final class RealOptionalBinder<T> extends OptionalBinder<T> implements Module {
+    private final Key<T> typeKey;
+    private final Key<Optional<T>> optionalKey;
+    private final Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey;
+    private final Key<Optional<Provider<T>>> optionalProviderKey;
+    private final Provider<Optional<Provider<T>>> optionalProviderT;
+    private final Key<T> defaultKey;
+    private final Key<T> actualKey;
+
+    private final Key javaOptionalKey;
+    private final Key javaOptionalJavaxProviderKey;
+    private final Key javaOptionalProviderKey;
+
+    /** the target injector's binder. non-null until initialization, null afterwards */
+    private Binder binder;
+    /** the default binding, for the SPI. */
+    private Binding<T> defaultBinding;
+    /** the actual binding, for the SPI */
+    private Binding<T> actualBinding;
+    
+    /** the dependencies -- initialized with defaults & overridden when tooled. */
+    private Set<Dependency<?>> dependencies;
+    /** the dependencies -- initialized with defaults & overridden when tooled. */
+    private Set<Dependency<?>> providerDependencies;
+
+    private RealOptionalBinder(Binder binder, Key<T> typeKey) {
+      this.binder = binder;
+      this.typeKey = checkNotNull(typeKey);
+      TypeLiteral<T> literal = typeKey.getTypeLiteral();
+      this.optionalKey = typeKey.ofType(optionalOf(literal));
+      this.optionalJavaxProviderKey = typeKey.ofType(optionalOfJavaxProvider(literal));
+      this.optionalProviderKey = typeKey.ofType(optionalOfProvider(literal));
+      this.optionalProviderT = binder.getProvider(optionalProviderKey);
+      String name = RealElement.nameOf(typeKey);
+      this.defaultKey = Key.get(typeKey.getTypeLiteral(), new DefaultImpl(name));
+      this.actualKey = Key.get(typeKey.getTypeLiteral(), new ActualImpl(name));
+      // Until the injector initializes us, we don't know what our dependencies are,
+      // so initialize to the whole Injector (like Multibinder, and MapBinder indirectly).
+      this.dependencies = ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
+      this.providerDependencies =
+          ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
+
+      if (JAVA_OPTIONAL_CLASS != null) {
+        this.javaOptionalKey = typeKey.ofType(javaOptionalOf(literal));
+        this.javaOptionalJavaxProviderKey = typeKey.ofType(javaOptionalOfJavaxProvider(literal));
+        this.javaOptionalProviderKey = typeKey.ofType(javaOptionalOfProvider(literal));
+      } else {
+        this.javaOptionalKey = null;
+        this.javaOptionalJavaxProviderKey = null;
+        this.javaOptionalProviderKey = null;
+      }
+    }
+
+    /**
+     * Adds a binding for T. Multiple calls to this are safe, and will be collapsed as duplicate
+     * bindings.
+     */
+    private void addDirectTypeBinding(Binder binder) {
+      binder.bind(typeKey).toProvider(new RealDirectTypeProvider());
+    }
+
+    Key<T> getKeyForDefaultBinding() {
+      checkConfiguration(!isInitialized(), "already initialized");      
+      addDirectTypeBinding(binder);
+      return defaultKey;
+    }
+
+    @Override public LinkedBindingBuilder<T> setDefault() {
+      return binder.bind(getKeyForDefaultBinding());
+    }
+    
+    Key<T> getKeyForActualBinding() {
+      checkConfiguration(!isInitialized(), "already initialized");      
+      addDirectTypeBinding(binder);
+      return actualKey;
+    }
+
+    @Override public LinkedBindingBuilder<T> setBinding() {
+      return binder.bind(getKeyForActualBinding());
+    }
+
+    @Override public void configure(Binder binder) {
+      checkConfiguration(!isInitialized(), "OptionalBinder was already initialized");
+
+      binder.bind(optionalProviderKey).toProvider(new RealOptionalProviderProvider());
+
+      // Optional is immutable, so it's safe to expose Optional<Provider<T>> as
+      // Optional<javax.inject.Provider<T>> (since Guice provider implements javax Provider).
+      @SuppressWarnings({"unchecked", "cast"})
+      Key massagedOptionalProviderKey = (Key) optionalProviderKey;
+      binder.bind(optionalJavaxProviderKey).to(massagedOptionalProviderKey);
+
+      binder.bind(optionalKey).toProvider(new RealOptionalKeyProvider());
+
+      // Bind the java-8 types if we know them.
+      bindJava8Optional(binder);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void bindJava8Optional(Binder binder) {
+      if (JAVA_OPTIONAL_CLASS != null) {
+        binder.bind(javaOptionalKey).toProvider(new JavaOptionalProvider());
+        binder.bind(javaOptionalProviderKey).toProvider(new JavaOptionalProviderProvider());
+        // for the javax version we reuse the guice version since they're type-compatible.
+        binder.bind(javaOptionalJavaxProviderKey).to(javaOptionalProviderKey);
+      }
+    }
+
+    @SuppressWarnings("rawtypes")
+    final class JavaOptionalProvider extends RealOptionalBinderProviderWithDependencies 
+        implements ProviderWithExtensionVisitor, OptionalBinderBinding {
+      private JavaOptionalProvider() {
+        super(typeKey);
+      }
+
+      @Override public Object get() {
+        Optional<Provider<T>> optional = optionalProviderT.get();
+        try {
+          if (optional.isPresent()) {
+            return JAVA_OF_NULLABLE_METHOD.invoke(JAVA_OPTIONAL_CLASS, optional.get().get());
+          } else {
+            return JAVA_EMPTY_METHOD.invoke(JAVA_OPTIONAL_CLASS);
+          }
+        } catch (IllegalAccessException e) {
+          throw new SecurityException(e);
+        } catch (IllegalArgumentException e) {
+          throw new IllegalStateException(e);
+        } catch (InvocationTargetException e) {
+          throw Throwables.propagate(e.getCause());
+        }
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        return dependencies;
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override public Object acceptExtensionVisitor(BindingTargetVisitor visitor,
+          ProviderInstanceBinding binding) {
+        if (visitor instanceof MultibindingsTargetVisitor) {
+          return ((MultibindingsTargetVisitor) visitor).visit(this);
+        } else {
+          return visitor.visit(binding);
+        }
+      }
+
+      @Override public boolean containsElement(Element element) {
+        return RealOptionalBinder.this.containsElement(element);
+      }
+
+      @Override public Binding getActualBinding() {
+        return RealOptionalBinder.this.getActualBinding();
+      }
+
+      @Override public Binding getDefaultBinding() {
+        return RealOptionalBinder.this.getDefaultBinding();
+      }
+
+      @Override public Key getKey() {
+        return javaOptionalKey;
+      }
+    }
+
+    @SuppressWarnings("rawtypes")
+    final class JavaOptionalProviderProvider extends RealOptionalBinderProviderWithDependencies {
+      private JavaOptionalProviderProvider() {
+        super(typeKey);
+      }
+
+      @Override public Object get() {
+        Optional<Provider<T>> optional = optionalProviderT.get();
+        try {
+          if (optional.isPresent()) {
+            return JAVA_OF_NULLABLE_METHOD.invoke(JAVA_OPTIONAL_CLASS, optional.get());
+          } else {
+            return JAVA_EMPTY_METHOD.invoke(JAVA_OPTIONAL_CLASS);
+          }
+        } catch (IllegalAccessException e) {
+          throw new SecurityException(e);
+        } catch (IllegalArgumentException e) {
+          throw new IllegalStateException(e);
+        } catch (InvocationTargetException e) {
+          throw Throwables.propagate(e.getCause());
+        }
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        return providerDependencies;
+      }
+    }
+
+    final class RealDirectTypeProvider extends RealOptionalBinderProviderWithDependencies<T> {
+      private RealDirectTypeProvider() {
+        super(typeKey);
+      }
+
+      @Override public T get() {
+        Optional<Provider<T>> optional = optionalProviderT.get();
+        if (optional.isPresent()) {
+          return optional.get().get();
+        }
+        // Let Guice handle blowing up if the injection point doesn't have @Nullable
+        // (If it does have @Nullable, that's fine.  This would only happen if
+        //  setBinding/setDefault themselves were bound to 'null').
+        return null;
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        return dependencies;
+      }
+    }
+
+    final class RealOptionalProviderProvider
+        extends RealOptionalBinderProviderWithDependencies<Optional<Provider<T>>> {
+      private Optional<Provider<T>> optional;
+
+      private RealOptionalProviderProvider() {
+        super(typeKey);
+      }
+
+      @Toolable @Inject void initialize(Injector injector) {
+        RealOptionalBinder.this.binder = null;
+        actualBinding = injector.getExistingBinding(actualKey);
+        defaultBinding = injector.getExistingBinding(defaultKey);
+        Binding<T> userBinding = injector.getExistingBinding(typeKey);
+        Binding<T> binding = null;
+        if (actualBinding != null) {
+          // TODO(sameb): Consider exposing an option that will allow
+          // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null.
+          // Right now, an ACTUAL binding can convert from present -> absent
+          // if it's bound to a provider that returns null.
+          binding = actualBinding;
+        } else if (defaultBinding != null) {
+          binding = defaultBinding;
+        } else if (userBinding != null) {
+          // If neither the actual or default is set, then we fallback
+          // to the value bound to the type itself and consider that the
+          // "actual binding" for the SPI.
+          binding = userBinding;
+          actualBinding = userBinding;
+        }
+          
+        if (binding != null) {
+          optional = Optional.of(binding.getProvider());
+          RealOptionalBinder.this.dependencies =
+              ImmutableSet.<Dependency<?>>of(Dependency.get(binding.getKey()));
+          RealOptionalBinder.this.providerDependencies =
+              ImmutableSet.<Dependency<?>>of(Dependency.get(providerOf(binding.getKey())));
+        } else {
+          optional = Optional.absent();
+          RealOptionalBinder.this.dependencies = ImmutableSet.of();
+          RealOptionalBinder.this.providerDependencies = ImmutableSet.of();
+        }
+      }
+        
+      @Override public Optional<Provider<T>> get() {
+        return optional;
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        return providerDependencies;
+      }
+    }
+
+    final class RealOptionalKeyProvider
+        extends RealOptionalBinderProviderWithDependencies<Optional<T>>
+        implements ProviderWithExtensionVisitor<Optional<T>>,
+            OptionalBinderBinding<Optional<T>>,
+            Provider<Optional<T>> {
+      private RealOptionalKeyProvider() {
+        super(typeKey);
+      }
+      
+      @Override public Optional<T> get() {
+        Optional<Provider<T>> optional = optionalProviderT.get();
+        if (optional.isPresent()) {
+          return Optional.fromNullable(optional.get().get());
+        } else {
+          return Optional.absent();
+        }
+      }
+
+      @Override public Set<Dependency<?>> getDependencies() {
+        return dependencies;
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public <B, R> R acceptExtensionVisitor(BindingTargetVisitor<B, R> visitor,
+          ProviderInstanceBinding<? extends B> binding) {
+        if (visitor instanceof MultibindingsTargetVisitor) {
+          return ((MultibindingsTargetVisitor<Optional<T>, R>) visitor).visit(this);
+        } else {
+          return visitor.visit(binding);
+        }
+      }
+
+      @Override public Key<Optional<T>> getKey() {
+        return optionalKey;
+      }
+
+      @Override public Binding<?> getActualBinding() {
+        return RealOptionalBinder.this.getActualBinding();
+      }
+
+      @Override public Binding<?> getDefaultBinding() {
+        return RealOptionalBinder.this.getDefaultBinding();
+      }
+
+      @Override public boolean containsElement(Element element) {
+        return RealOptionalBinder.this.containsElement(element);
+      }
+    }
+
+    private Binding<?> getActualBinding() {
+      if (isInitialized()) {
+        return actualBinding;
+      } else {
+        throw new UnsupportedOperationException(
+            "getActualBinding() not supported from Elements.getElements, requires an Injector.");
+      }
+    }
+
+    private Binding<?> getDefaultBinding() {
+      if (isInitialized()) {
+        return defaultBinding;
+      } else {
+        throw new UnsupportedOperationException(
+            "getDefaultBinding() not supported from Elements.getElements, requires an Injector.");
+      }
+    }
+
+    private boolean containsElement(Element element) {
+      Key<?> elementKey;
+      if (element instanceof Binding) {
+        elementKey = ((Binding<?>) element).getKey();
+      } else if (element instanceof ProviderLookup) {
+        elementKey = ((ProviderLookup<?>) element).getKey();
+      } else {
+        return false; // cannot match;
+      }
+
+      return elementKey.equals(optionalKey)
+          || elementKey.equals(optionalProviderKey)
+          || elementKey.equals(optionalJavaxProviderKey)
+          || elementKey.equals(defaultKey)
+          || elementKey.equals(actualKey)
+          || matchesJ8Keys(elementKey)
+          || matchesTypeKey(element, elementKey);
+    }
+
+    private boolean matchesJ8Keys(Key<?> elementKey) {
+      if (JAVA_OPTIONAL_CLASS != null) {
+        return elementKey.equals(javaOptionalKey)
+            || elementKey.equals(javaOptionalProviderKey)
+            || elementKey.equals(javaOptionalJavaxProviderKey);
+      }
+      return false;
+    }
+    
+    /** Returns true if the key & element indicate they were bound by this OptionalBinder. */
+    private boolean matchesTypeKey(Element element, Key<?> elementKey) {
+      // Just doing .equals(typeKey) isn't enough, because the user can bind that themselves.
+      return elementKey.equals(typeKey)
+          && element instanceof ProviderInstanceBinding
+          && (((ProviderInstanceBinding) element)
+              .getUserSuppliedProvider() instanceof RealOptionalBinderProviderWithDependencies);
+    }
+
+    private boolean isInitialized() {
+      return binder == null;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o instanceof RealOptionalBinder
+          && ((RealOptionalBinder<?>) o).typeKey.equals(typeKey);
+    }
+
+    @Override public int hashCode() {
+      return typeKey.hashCode();
+    }
+
+    /**
+     * A base class for ProviderWithDependencies that need equality based on a specific object.
+     */
+    private abstract static class RealOptionalBinderProviderWithDependencies<T> implements
+        ProviderWithDependencies<T> {
+      private final Object equality;
+
+      public RealOptionalBinderProviderWithDependencies(Object equality) {
+        this.equality = equality;
+      }
+
+      @Override public boolean equals(Object obj) {
+        return this.getClass() == obj.getClass()
+            && equality.equals(((RealOptionalBinderProviderWithDependencies<?>) obj).equality);
+      }
+
+      @Override public int hashCode() {
+        return equality.hashCode();
+      }
+    }
+  }
+  
+  static class DefaultImpl extends BaseAnnotation implements Default {
+    public DefaultImpl(String value) {
+      super(Default.class, value);
+    }
+  }
+  
+  static class ActualImpl extends BaseAnnotation implements Actual {
+    public ActualImpl(String value) {
+      super(Actual.class, value);
+    }
+  }
+  
+  abstract static class BaseAnnotation implements Serializable, Annotation {
+
+    private final String value;
+    private final Class<? extends Annotation> clazz;
+
+    BaseAnnotation(Class<? extends Annotation> clazz, String value) {
+      this.clazz = checkNotNull(clazz, "clazz");
+      this.value = checkNotNull(value, "value");
+    }
+
+    public String value() {
+      return this.value;
+    }
+
+    @Override public int hashCode() {
+      // This is specified in java.lang.Annotation.
+      return (127 * "value".hashCode()) ^ value.hashCode();
+    }
+
+    @Override public boolean equals(Object o) {
+      // We check against each annotation type instead of BaseAnnotation
+      // so that we can compare against generated annotation implementations. 
+      if (o instanceof Actual && clazz == Actual.class) {
+        Actual other = (Actual) o;
+        return value.equals(other.value());
+      } else if (o instanceof Default && clazz == Default.class) {
+        Default other = (Default) o;
+        return value.equals(other.value());
+      }
+      return false;
+    }
+
+    @Override public String toString() {
+      return "@" + clazz.getName() + (value.isEmpty() ? "" : "(value=" + value + ")");
+    }
+
+    @Override public Class<? extends Annotation> annotationType() {
+      return clazz;
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinderBinding.java b/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinderBinding.java
new file mode 100644
index 0000000..fbbbc36
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinderBinding.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 2014 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.inject.multibindings;
+
+import com.google.inject.Binding;
+import com.google.inject.Key;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+
+/**
+ * A binding for a OptionalBinder.
+ * 
+ * <p>Although OptionalBinders may be injected through a variety of types
+ * {@code T}, {@code Optional<T>}, {@code Optional<Provider<T>>}, etc..), an
+ * OptionalBinderBinding exists only on the Binding associated with the
+ * {@code Optional<T>} key.  Other bindings can be validated to be derived from this
+ * OptionalBinderBinding using {@link #containsElement}.
+ * 
+ * @param <T> The fully qualified type of the optional binding, including Optional.
+ *        For example: {@code Optional<String>}.
+ * 
+ * @since 4.0
+ * @author sameb@google.com (Sam Berlin)
+ */
+public interface OptionalBinderBinding<T> {
+
+  /** Returns the {@link Key} for this binding. */
+  Key<T> getKey();
+  
+  /**
+   * Returns the default binding (set by {@link OptionalBinder#setDefault}) if one exists or null
+   * if no default binding is set. This will throw {@link UnsupportedOperationException} if it is
+   * called on an element retrieved from {@link Elements#getElements}.
+   * <p>
+   * The Binding's type will always match the type Optional's generic type. For example, if getKey
+   * returns a key of <code>Optional&lt;String></code>, then this will always return a
+   * <code>Binding&lt;String></code>.
+   */
+  Binding<?> getDefaultBinding();
+  
+  /**
+   * Returns the actual binding (set by {@link OptionalBinder#setBinding}) or null if not set.
+   * This will throw {@link UnsupportedOperationException} if it is called on an element retrieved
+   * from {@link Elements#getElements}.
+   * <p>
+   * The Binding's type will always match the type Optional's generic type. For example, if getKey
+   * returns a key of <code>Optional&lt;String></code>, then this will always return a
+   * <code>Binding&lt;String></code>.
+   */
+  Binding<?> getActualBinding();
+
+  /**
+   * Returns true if this OptionalBinder contains the given Element in order to build the optional
+   * binding or uses the given Element in order to support building and injecting its data. This
+   * will work for OptionalBinderBinding retrieved from an injector and
+   * {@link Elements#getElements}. Usually this is only necessary if you are working with elements
+   * retrieved from modules (without an Injector), otherwise {@link #getDefaultBinding} and
+   * {@link #getActualBinding} are better options.
+   */
+  boolean containsElement(Element element);
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoMap.java b/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoMap.java
new file mode 100644
index 0000000..886a0fd
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoMap.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2015 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.inject.multibindings;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.Module;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates methods of a {@link Module} to add items to a {@link MapBinder}.
+ * The method's return type, binding annotation and additional key annotation determines
+ * what Map this will contribute to. For example,
+ *
+ * <pre>
+ * {@literal @}ProvidesIntoMap
+ * {@literal @}StringMapKey("Foo")
+ * {@literal @}Named("plugins")
+ * Plugin provideFooUrl(FooManager fm) { returm fm.getPlugin(); }
+ *
+ * {@literal @}ProvidesIntoMap
+ * {@literal @}StringMapKey("Bar")
+ * {@literal @}Named("urls")
+ * Plugin provideBarUrl(BarManager bm) { return bm.getPlugin(); }
+ * </pre>
+ *
+ * will add two items to the {@code @Named("urls") Map<String, Plugin>} map. The key 'Foo'
+ * will map to the provideFooUrl method, and the key 'Bar' will map to the provideBarUrl method.
+ * The values are bound as providers and will be evaluated at injection time.
+ *
+ * <p>Because the key is specified as an annotation, only Strings, Classes, enums, primitive
+ * types and annotation instances are supported as keys.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+@Documented
+@Target(METHOD)
+@Retention(RUNTIME)
+public @interface ProvidesIntoMap {
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoOptional.java b/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoOptional.java
new file mode 100644
index 0000000..23576f6
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoOptional.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2015 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.inject.multibindings;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.Module;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates methods of a {@link Module} to add items to a {@link Multibinder}.
+ * The method's return type and binding annotation determines what Optional this will
+ * contribute to. For example,
+ *
+ * <pre>
+ * {@literal @}ProvidesIntoOptional(DEFAULT)
+ * {@literal @}Named("url")
+ * String provideFooUrl(FooManager fm) { returm fm.getUrl(); }
+ *
+ * {@literal @}ProvidesIntoOptional(ACTUAL)
+ * {@literal @}Named("url")
+ * String provideBarUrl(BarManager bm) { return bm.getUrl(); }
+ * </pre>
+ *
+ * will set the default value of {@code @Named("url") Optional<String>} to foo's URL,
+ * and then override it to bar's URL.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+@Documented
+@Target(METHOD)
+@Retention(RUNTIME)
+public @interface ProvidesIntoOptional {
+  /**
+   * @since 4.0
+   */
+  enum Type {
+    /** Corresponds to {@link OptionalBinder#setBinding}. */
+    ACTUAL,
+
+    /** Corresponds to {@link OptionalBinder#setDefault}. */
+    DEFAULT
+  }
+
+  /** Specifies if the binding is for the actual or default value. */
+  Type value();
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoSet.java b/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoSet.java
new file mode 100644
index 0000000..b26df68
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/ProvidesIntoSet.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2015 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.inject.multibindings;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.Module;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates methods of a {@link Module} to add items to a {@link Multibinder}.
+ * The method's return type and binding annotation determines what Set this will
+ * contribute to. For example,
+ *
+ * <pre>
+ * {@literal @}ProvidesIntoSet
+ * {@literal @}Named("urls")
+ * String provideFooUrl(FooManager fm) { returm fm.getUrl(); }
+ *
+ * {@literal @}ProvidesIntoSet
+ * {@literal @}Named("urls")
+ * String provideBarUrl(BarManager bm) { return bm.getUrl(); }
+ * </pre>
+ *
+ * will add two items to the {@code @Named("urls") Set<String>} set. The items are bound as
+ * providers and will be evaluated at injection time.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+@Documented
+@Target(METHOD)
+@Retention(RUNTIME)
+public @interface ProvidesIntoSet {
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/RealElement.java b/extensions/multibindings/src/com/google/inject/multibindings/RealElement.java
new file mode 100644
index 0000000..e018f49
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/RealElement.java
@@ -0,0 +1,104 @@
+/**
+ * Copyright (C) 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.inject.multibindings;
+
+import com.google.inject.Key;
+import com.google.inject.internal.Annotations;
+
+import java.lang.annotation.Annotation;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/** An implementation of Element. */
+// TODO(cgruber): Use AutoAnnotation when available, here & wherever else is makes sense.
+class RealElement implements Element {
+  private static final AtomicInteger nextUniqueId = new AtomicInteger(1);
+  
+  private final int uniqueId;
+  private final String setName;
+  private final Element.Type type;
+  private final String keyType;
+
+  RealElement(String setName, Element.Type type, String keyType) {
+    this(setName, type, keyType, nextUniqueId.incrementAndGet());
+  }
+  
+  RealElement(String setName, Element.Type type, String keyType, int uniqueId) {
+    this.uniqueId = uniqueId;
+    this.setName = setName;
+    this.type = type;
+    this.keyType = keyType;
+  }
+  
+  @Override public String setName() {
+    return setName;
+  }
+  
+  @Override public int uniqueId() {
+    return uniqueId;
+  }
+  
+  @Override public Element.Type type() {
+    return type;
+  }
+  
+  @Override public String keyType() {
+    return keyType;
+  }
+
+  @Override public Class<? extends Annotation> annotationType() {
+    return Element.class;
+  }
+  
+  @Override public String toString() {
+    return "@" + Element.class.getName() + "(setName=" + setName
+        + ",uniqueId=" + uniqueId + ", type=" + type + ", keyType=" + keyType + ")";
+  }
+
+  @Override public boolean equals(Object o) {
+    return o instanceof Element
+        && ((Element) o).setName().equals(setName())
+        && ((Element) o).uniqueId() == uniqueId()
+        && ((Element) o).type() == type()
+        && ((Element) o).keyType().equals(keyType());
+  }
+
+  @Override public int hashCode() {
+    return ((127 * "setName".hashCode()) ^ setName.hashCode())
+        + ((127 * "uniqueId".hashCode()) ^ uniqueId)
+        + ((127 * "type".hashCode()) ^ type.hashCode())
+        + ((127 * "keyType".hashCode()) ^ keyType.hashCode());
+  }
+
+  /**
+   * Returns the name the binding should use.  This is based on the annotation.
+   * If the annotation has an instance and is not a marker annotation,
+   * we ask the annotation for its toString.  If it was a marker annotation
+   * or just an annotation type, we use the annotation's name. Otherwise,
+   * the name is the empty string.
+   */
+  static String nameOf(Key<?> key) {
+    Annotation annotation = key.getAnnotation();
+    Class<? extends Annotation> annotationType = key.getAnnotationType();
+    if (annotation != null && !Annotations.isMarker(annotationType)) {
+      return key.getAnnotation().toString();
+    } else if (key.getAnnotationType() != null) {
+      return "@" + key.getAnnotationType().getName();
+    } else {
+      return "";
+    }
+  }
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/StringMapKey.java b/extensions/multibindings/src/com/google/inject/multibindings/StringMapKey.java
new file mode 100644
index 0000000..9a4f1bd
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/StringMapKey.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2015 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.inject.multibindings;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Allows {@literal @}{@link ProvidesIntoMap} to specify a string map key.
+ *
+ * @since 4.0
+ */
+@MapKey(unwrapValue = true)
+@Documented
+@Target(METHOD)
+@Retention(RUNTIME)
+public @interface StringMapKey {
+  String value();
+}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/package-info.java b/extensions/multibindings/src/com/google/inject/multibindings/package-info.java
new file mode 100644
index 0000000..7151779
--- /dev/null
+++ b/extensions/multibindings/src/com/google/inject/multibindings/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * Extension for binding multiple instances in a collection; this extension requires {@code
+ * guice-multibindings.jar}.
+ */
+package com.google.inject.multibindings;
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/AllTests.java b/extensions/multibindings/test/com/google/inject/multibindings/AllTests.java
new file mode 100644
index 0000000..6806edd
--- /dev/null
+++ b/extensions/multibindings/test/com/google/inject/multibindings/AllTests.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 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.inject.multibindings;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class AllTests {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+    suite.addTestSuite(MapBinderTest.class);
+    suite.addTestSuite(MultibinderTest.class);
+    suite.addTestSuite(OptionalBinderTest.class);
+    suite.addTestSuite(RealElementTest.class);
+    suite.addTestSuite(ProvidesIntoTest.class);
+    return suite;
+  }
+}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/Collector.java b/extensions/multibindings/test/com/google/inject/multibindings/Collector.java
new file mode 100644
index 0000000..18f2527
--- /dev/null
+++ b/extensions/multibindings/test/com/google/inject/multibindings/Collector.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2014 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.inject.multibindings;
+
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+
+class Collector extends DefaultBindingTargetVisitor<Object, Object> implements
+    MultibindingsTargetVisitor<Object, Object> {
+  MapBinderBinding<? extends Object> mapbinding;
+  MultibinderBinding<? extends Object> setbinding;
+  OptionalBinderBinding<? extends Object> optionalbinding;
+
+  @Override
+  public Object visit(MapBinderBinding<? extends Object> mapbinding) {
+    this.mapbinding = mapbinding;
+    return null;
+  }
+
+  @Override
+  public Object visit(MultibinderBinding<? extends Object> multibinding) {
+   this.setbinding = multibinding;
+   return null;
+  }
+  
+  @Override
+  public Object visit(OptionalBinderBinding<? extends Object> optionalbinding) {
+    this.optionalbinding = optionalbinding;
+    return null;
+  }
+}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
new file mode 100644
index 0000000..4206521
--- /dev/null
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
@@ -0,0 +1,1032 @@
+/**
+ * Copyright (C) 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.inject.multibindings;
+
+import static com.google.inject.Asserts.asModuleChain;
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH;
+import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE;
+import static com.google.inject.multibindings.SpiUtils.assertMapVisitor;
+import static com.google.inject.multibindings.SpiUtils.instance;
+import static com.google.inject.multibindings.SpiUtils.providerInstance;
+import static com.google.inject.name.Names.named;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Asserts;
+import com.google.inject.Binding;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.ConfigurationException;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.WeakKeySetUtils;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.util.Modules;
+import com.google.inject.util.Providers;
+import com.google.inject.util.Types;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author dpb@google.com (David P. Baker)
+ */
+public class MapBinderTest extends TestCase {
+
+  private static final Set<Key<?>> FRAMEWORK_KEYS = ImmutableSet.of(
+      Key.get(java.util.logging.Logger.class),
+      Key.get(Stage.class),
+      Key.get(Injector.class)
+  );
+
+  final TypeLiteral<Map<String, javax.inject.Provider<String>>> mapOfStringJavaxProvider =
+      new TypeLiteral<Map<String, javax.inject.Provider<String>>>() {};
+  final TypeLiteral<Map<String, Provider<String>>> mapOfStringProvider =
+      new TypeLiteral<Map<String, Provider<String>>>() {}; 
+  final TypeLiteral<Map<String, String>> mapOfString = new TypeLiteral<Map<String, String>>() {};
+  final TypeLiteral<Map<Integer, String>> mapOfIntString =
+      new TypeLiteral<Map<Integer, String>>() {};
+  final TypeLiteral<Map<String, Integer>> mapOfInteger = new TypeLiteral<Map<String, Integer>>() {};
+  final TypeLiteral<Map<String, Set<String>>> mapOfSetOfString =
+      new TypeLiteral<Map<String, Set<String>>>() {};
+      
+  private final TypeLiteral<String> stringType = TypeLiteral.get(String.class);
+  private final TypeLiteral<Integer> intType = TypeLiteral.get(Integer.class);
+
+  private Type javaxProviderOf(Type type) {
+    return Types.newParameterizedType(javax.inject.Provider.class, type);
+  }
+
+  private Type mapEntryOf(Type keyType, Type valueType) {
+    return Types.newParameterizedTypeWithOwner(Map.class, Map.Entry.class, keyType, valueType);
+  }
+
+  private Type collectionOf(Type type) {
+    return Types.newParameterizedType(Collection.class, type);
+  }
+
+  public void testAllBindings() {
+    Module module = new AbstractModule() {
+      @Override
+      protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, String.class).permitDuplicates();
+      }
+    };
+
+    Injector injector = Guice.createInjector(module);
+
+    Map<Key<?>, Binding<?>> bindings = injector.getBindings();
+
+    ImmutableSet<Key<?>> expectedBindings = ImmutableSet.<Key<?>>builder()
+        .add(
+            // Map<K, V>
+            Key.get(Types.mapOf(String.class, String.class)),
+            // Map<K, Provider<V>>
+            Key.get(Types.mapOf(String.class, Types.providerOf(String.class))),
+            // Map<K, javax.inject.Provider<V>>
+            Key.get(Types.mapOf(String.class, javaxProviderOf(String.class))),
+            // Map<K, Set<V>>
+            Key.get(Types.mapOf(String.class, Types.setOf(String.class))),
+            // Map<K, Set<Provider<V>>
+            Key.get(Types.mapOf(String.class, Types.setOf(Types.providerOf(String.class)))),
+            // Set<Map.Entry<K, Provider<V>>>
+            Key.get(Types.setOf(mapEntryOf(String.class, Types.providerOf(String.class)))),
+            // Collection<Provider<Map.Entry<K, Provider<V>>>>
+            Key.get(collectionOf(Types.providerOf(
+                mapEntryOf(String.class, Types.providerOf(String.class))))),
+            // Collection<javax.inject.Provider<Map.Entry<K, Provider<V>>>>
+            Key.get(collectionOf(javaxProviderOf(
+                mapEntryOf(String.class, Types.providerOf(String.class))))),
+            // @Named(...) Boolean
+            Key.get(Boolean.class,
+                named("Multibinder<java.util.Map$Entry<java.lang.String, "
+                    + "com.google.inject.Provider<java.lang.String>>> permits duplicates"))
+        )
+        .addAll(FRAMEWORK_KEYS).build();
+
+    Set<Key<?>> missingBindings = Sets.difference(expectedBindings, bindings.keySet());
+    Set<Key<?>> extraBindings = Sets.difference(bindings.keySet(), expectedBindings);
+
+    assertTrue("There should be no missing bindings. Missing: " + missingBindings,
+        missingBindings.isEmpty());
+    assertTrue("There should be no extra bindings. Extra: " + extraBindings,
+        extraBindings.isEmpty());
+  }
+
+  public void testMapBinderAggregatesMultipleModules() {
+    Module abc = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B");
+        multibinder.addBinding("c").toInstance("C");
+      }
+    };
+    Module de = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class);
+        multibinder.addBinding("d").toInstance("D");
+        multibinder.addBinding("e").toInstance("E");
+      }
+    };
+
+    Injector injector = Guice.createInjector(abc, de);
+    Map<String, String> abcde = injector.getInstance(Key.get(mapOfString));
+
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E"), abcde);
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abc, de), BOTH, false, 0,
+        instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("d", "D"), instance("e", "E"));
+
+    // just make sure these succeed
+    injector.getInstance(Key.get(mapOfStringProvider));
+    injector.getInstance(Key.get(mapOfStringJavaxProvider));
+  }
+
+  public void testMapBinderAggregationForAnnotationInstance() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, Names.named("abc"));
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B");
+
+        multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, Names.named("abc"));
+        multibinder.addBinding("c").toInstance("C");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Key<Map<String, String>> key = Key.get(mapOfString, Names.named("abc"));
+    Map<String, String> abc = injector.getInstance(key);
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc);
+    assertMapVisitor(key, stringType, stringType, setOf(module), BOTH, false, 0,
+        instance("a", "A"), instance("b", "B"), instance("c", "C"));
+    
+    // just make sure these succeed
+    injector.getInstance(Key.get(mapOfStringProvider, Names.named("abc")));
+    injector.getInstance(Key.get(mapOfStringJavaxProvider, Names.named("abc")));
+  }
+
+  public void testMapBinderAggregationForAnnotationType() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, Abc.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B");
+
+        multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, Abc.class);
+        multibinder.addBinding("c").toInstance("C");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Key<Map<String, String>> key = Key.get(mapOfString, Abc.class);
+    Map<String, String> abc = injector.getInstance(key);
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc);
+    assertMapVisitor(key, stringType, stringType, setOf(module), BOTH, false, 0,
+        instance("a", "A"), instance("b", "B"), instance("c", "C"));
+    
+    // just make sure these succeed
+    injector.getInstance(Key.get(mapOfStringProvider, Abc.class));
+    injector.getInstance(Key.get(mapOfStringJavaxProvider, Abc.class));
+  }
+
+  public void testMapBinderWithMultipleAnnotationValueSets() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> abcMapBinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, named("abc"));
+        abcMapBinder.addBinding("a").toInstance("A");
+        abcMapBinder.addBinding("b").toInstance("B");
+        abcMapBinder.addBinding("c").toInstance("C");
+
+        MapBinder<String, String> deMapBinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, named("de"));
+        deMapBinder.addBinding("d").toInstance("D");
+        deMapBinder.addBinding("e").toInstance("E");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Key<Map<String, String>> abcKey = Key.get(mapOfString, named("abc"));
+    Map<String, String> abc = injector.getInstance(abcKey);
+    Key<Map<String, String>> deKey = Key.get(mapOfString, named("de"));
+    Map<String, String> de = injector.getInstance(deKey);
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc);
+    assertEquals(mapOf("d", "D", "e", "E"), de);
+    assertMapVisitor(abcKey, stringType, stringType, setOf(module), BOTH, false, 1,
+        instance("a", "A"), instance("b", "B"), instance("c", "C"));
+    assertMapVisitor(deKey, stringType, stringType, setOf(module), BOTH, false, 1,
+        instance("d", "D"), instance("e", "E"));     
+    
+    // just make sure these succeed
+    injector.getInstance(Key.get(mapOfStringProvider, named("abc")));
+    injector.getInstance(Key.get(mapOfStringJavaxProvider, named("abc")));
+    injector.getInstance(Key.get(mapOfStringProvider, named("de")));
+    injector.getInstance(Key.get(mapOfStringJavaxProvider, named("de")));
+  }
+
+  public void testMapBinderWithMultipleAnnotationTypeSets() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> abcMapBinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, Abc.class);
+        abcMapBinder.addBinding("a").toInstance("A");
+        abcMapBinder.addBinding("b").toInstance("B");
+        abcMapBinder.addBinding("c").toInstance("C");
+
+        MapBinder<String, String> deMapBinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, De.class);
+        deMapBinder.addBinding("d").toInstance("D");
+        deMapBinder.addBinding("e").toInstance("E");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Key<Map<String, String>> abcKey = Key.get(mapOfString, Abc.class);
+    Map<String, String> abc = injector.getInstance(abcKey);
+    Key<Map<String, String>> deKey = Key.get(mapOfString, De.class);
+    Map<String, String> de = injector.getInstance(deKey);
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc);
+    assertEquals(mapOf("d", "D", "e", "E"), de);
+    assertMapVisitor(abcKey, stringType, stringType, setOf(module), BOTH, false, 1,
+        instance("a", "A"), instance("b", "B"), instance("c", "C"));
+    assertMapVisitor(deKey, stringType, stringType, setOf(module), BOTH, false, 1,
+        instance("d", "D"), instance("e", "E"));
+    
+    // just make sure these succeed
+    injector.getInstance(Key.get(mapOfStringProvider, Abc.class));
+    injector.getInstance(Key.get(mapOfStringJavaxProvider, Abc.class));
+    injector.getInstance(Key.get(mapOfStringProvider, De.class));
+    injector.getInstance(Key.get(mapOfStringJavaxProvider, De.class));
+  }
+
+  public void testMapBinderWithMultipleTypes() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, String.class)
+            .addBinding("a").toInstance("A");
+        MapBinder.newMapBinder(binder(), String.class, Integer.class)
+            .addBinding("1").toInstance(1);
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(mapOf("a", "A"), injector.getInstance(Key.get(mapOfString)));
+    assertEquals(mapOf("1", 1), injector.getInstance(Key.get(mapOfInteger)));
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 1,
+        instance("a", "A"));
+    assertMapVisitor(Key.get(mapOfInteger), stringType, intType, setOf(module), BOTH, false, 1,
+        instance("1", 1));
+  }
+
+  public void testMapBinderWithEmptyMap() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, String.class);
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Map<String, String> map = injector.getInstance(Key.get(mapOfString));
+    assertEquals(Collections.emptyMap(), map);
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 0);
+  }
+
+  public void testMapBinderMapIsUnmodifiable() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, String.class)
+            .addBinding("a").toInstance("A");
+      }
+    });
+
+    Map<String, String> map = injector.getInstance(Key.get(mapOfString));
+    try {
+      map.clear();
+      fail();
+    } catch(UnsupportedOperationException expected) {
+    }
+  }
+
+  public void testMapBinderMapIsLazy() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, Integer.class)
+            .addBinding("num").toProvider(new Provider<Integer>() {
+          int nextValue = 1;
+          @Override public Integer get() {
+            return nextValue++;
+          }
+        });
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(mapOf("num", 1), injector.getInstance(Key.get(mapOfInteger)));
+    assertEquals(mapOf("num", 2), injector.getInstance(Key.get(mapOfInteger)));
+    assertEquals(mapOf("num", 3), injector.getInstance(Key.get(mapOfInteger)));
+    assertMapVisitor(Key.get(mapOfInteger), stringType, intType, setOf(module), BOTH, false, 0,
+        providerInstance("num", 1));
+  }
+
+  public void testMapBinderMapForbidsDuplicateKeys() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("a").toInstance("B");
+      }
+    };
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(),
+          "Map injection failed due to duplicated key \"a\"");
+    }
+    
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), MODULE, false, 0,
+        instance("a", "A"), instance("a", "B"));
+  }
+
+  public void testExhaustiveDuplicateErrorMessage() throws Exception {
+    class Module1 extends AbstractModule {
+      @Override protected void configure() {
+        MapBinder<String, Object> mapbinder =
+            MapBinder.newMapBinder(binder(), String.class, Object.class);
+        mapbinder.addBinding("a").to(String.class);
+      }
+    }
+    class Module2 extends AbstractModule {
+      @Override protected void configure() {
+        MapBinder<String, Object> mapbinder =
+            MapBinder.newMapBinder(binder(), String.class, Object.class);
+        mapbinder.addBinding("a").to(Integer.class);
+        mapbinder.addBinding("b").to(String.class);
+      }
+    }
+    class Module3 extends AbstractModule {
+      @Override protected void configure() {
+        MapBinder<String, Object> mapbinder =
+            MapBinder.newMapBinder(binder(), String.class, Object.class);
+        mapbinder.addBinding("b").to(Integer.class);
+      }
+    }
+    class Main extends AbstractModule {
+      @Override protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, Object.class);
+        install(new Module1());
+        install(new Module2());
+        install(new Module3());
+      }
+      @Provides String provideString() { return "foo"; }
+      @Provides Integer provideInt() { return 42; }
+    }
+    try {
+      Guice.createInjector(new Main());
+      fail();
+    } catch(CreationException ce) {
+      assertContains(ce.getMessage(),
+          "Map injection failed due to duplicated key \"a\", from bindings:",
+          asModuleChain(Main.class, Module1.class),
+          asModuleChain(Main.class, Module2.class),
+          "and key: \"b\", from bindings:",
+          asModuleChain(Main.class, Module2.class),
+          asModuleChain(Main.class, Module3.class),
+          "at " + Main.class.getName() + ".configure(",
+          asModuleChain(Main.class, MapBinder.RealMapBinder.class));
+      assertEquals(1, ce.getErrorMessages().size());
+    }
+  }
+
+  public void testMapBinderMapPermitDuplicateElements() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B");
+        multibinder.permitDuplicates();
+      }
+    };
+    Module bc = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class);
+        multibinder.addBinding("b").toInstance("B");
+        multibinder.addBinding("c").toInstance("C");
+        multibinder.permitDuplicates();
+      }
+    };
+    Injector injector = Guice.createInjector(ab, bc);
+
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injector.getInstance(Key.get(mapOfString)));
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(ab, bc), BOTH, true, 0,
+        instance("a", "A"), instance("b", "B"), instance("c", "C"));
+  }
+
+  public void testMapBinderMapDoesNotDedupeDuplicateValues() {
+    class ValueType {
+      int keyPart;
+      int dataPart;
+      private ValueType(int keyPart, int dataPart) {
+        this.keyPart = keyPart;
+        this.dataPart = dataPart;
+      }
+      @Override
+      public boolean equals(Object obj) {
+        return (obj instanceof ValueType) && (keyPart == ((ValueType) obj).keyPart);
+      }
+      @Override
+      public int hashCode() {
+        return keyPart;
+      }
+    }
+    Module m1 = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, ValueType> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, ValueType.class);
+        multibinder.addBinding("a").toInstance(new ValueType(1, 2));
+      }
+    };
+    Module m2 = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, ValueType> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, ValueType.class);
+        multibinder.addBinding("b").toInstance(new ValueType(1, 3));
+      }
+    };
+    
+    Injector injector = Guice.createInjector(m1, m2);
+    Map<String, ValueType> map = injector.getInstance(new Key<Map<String, ValueType>>() {});
+    assertEquals(2, map.get("a").dataPart);
+    assertEquals(3, map.get("b").dataPart);
+  }
+
+  public void testMapBinderMultimap() {
+    AbstractModule ab1c = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B1");
+        multibinder.addBinding("c").toInstance("C");
+      }
+    };
+    AbstractModule b2c = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class);
+        multibinder.addBinding("b").toInstance("B2");
+        multibinder.addBinding("c").toInstance("C");
+        multibinder.permitDuplicates();
+      }
+    };
+    Injector injector = Guice.createInjector(ab1c, b2c);
+
+    assertEquals(mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")),
+        injector.getInstance(Key.get(mapOfSetOfString)));
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(ab1c, b2c), BOTH, true, 0,
+        instance("a", "A"), instance("b", "B1"), instance("b", "B2"), instance("c", "C"));
+  }
+
+  public void testMapBinderMultimapWithAnotation() {
+    AbstractModule ab1 = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, Abc.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B1");
+      }
+    };
+    AbstractModule b2c = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class, Abc.class);
+        multibinder.addBinding("b").toInstance("B2");
+        multibinder.addBinding("c").toInstance("C");
+        multibinder.permitDuplicates();
+      }
+    };
+    Injector injector = Guice.createInjector(ab1, b2c);
+
+    assertEquals(mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")),
+        injector.getInstance(Key.get(mapOfSetOfString, Abc.class)));
+    try {
+      injector.getInstance(Key.get(mapOfSetOfString));
+      fail();
+    } catch (ConfigurationException expected) {}
+    
+    assertMapVisitor(Key.get(mapOfString, Abc.class), stringType, stringType, setOf(ab1, b2c), BOTH, true, 0,
+        instance("a", "A"), instance("b", "B1"), instance("b", "B2"), instance("c", "C"));
+  }
+
+  public void testMapBinderMultimapIsUnmodifiable() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> mapBinder = MapBinder.newMapBinder(
+            binder(), String.class, String.class);
+        mapBinder.addBinding("a").toInstance("A");
+        mapBinder.permitDuplicates();
+      }
+    });
+
+    Map<String, Set<String>> map = injector.getInstance(Key.get(mapOfSetOfString));
+    try {
+      map.clear();
+      fail();
+    } catch(UnsupportedOperationException expected) {
+    }
+    try {
+      map.get("a").clear();
+      fail();
+    } catch(UnsupportedOperationException expected) {
+    }
+  }
+
+  public void testMapBinderMapForbidsNullKeys() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          MapBinder.newMapBinder(binder(), String.class, String.class).addBinding(null);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {}
+  }
+
+  public void testMapBinderMapForbidsNullValues() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, String.class)
+            .addBinding("null").toProvider(Providers.<String>of(null));
+      }
+    };
+    Injector injector = Guice.createInjector(m);
+
+    try {
+      injector.getInstance(Key.get(mapOfString));
+      fail();
+    } catch(ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "1) Map injection failed due to null value for key \"null\", bound at: "
+          + m.getClass().getName() + ".configure(");
+    }
+  }
+
+  public void testMapBinderProviderIsScoped() {
+    final Provider<Integer> counter = new Provider<Integer>() {
+      int next = 1;
+      @Override public Integer get() {
+        return next++;
+      }
+    };
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, Integer.class)
+            .addBinding("one").toProvider(counter).asEagerSingleton();
+      }
+    });
+
+    assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one"));
+    assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one"));
+  }
+
+  public void testSourceLinesInMapBindings() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          MapBinder.newMapBinder(binder(), String.class, Integer.class)
+              .addBinding("one");
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for java.lang.Integer",
+          "at " + getClass().getName());
+    }
+  }
+
+  /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */
+  public void testMultibinderDependencies() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<Integer, String> mapBinder
+            = MapBinder.newMapBinder(binder(), Integer.class, String.class);
+        mapBinder.addBinding(1).toInstance("A");
+        mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b")));
+
+        bindConstant().annotatedWith(Names.named("b")).to("B");
+      }
+    });
+
+    Binding<Map<Integer, String>> binding = injector.getBinding(new Key<Map<Integer, String>>() {});
+    HasDependencies withDependencies = (HasDependencies) binding;
+    Key<?> setKey = new Key<Set<Map.Entry<Integer, Provider<String>>>>() {};
+    assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(setKey)),
+        withDependencies.getDependencies());
+    Set<String> elements = Sets.newHashSet();
+    elements.addAll(recurseForDependencies(injector, withDependencies));
+    assertEquals(ImmutableSet.of("A", "B"), elements);
+  }
+
+  private Set<String> recurseForDependencies(Injector injector, HasDependencies hasDependencies) {
+    Set<String> elements = Sets.newHashSet();
+    for (Dependency<?> dependency : hasDependencies.getDependencies()) {
+      Binding<?> binding = injector.getBinding(dependency.getKey());
+      HasDependencies deps = (HasDependencies) binding;
+      if (binding instanceof InstanceBinding) {
+        elements.add((String) ((InstanceBinding<?>) binding).getInstance());
+      } else {
+        elements.addAll(recurseForDependencies(injector, deps));
+      }
+    }    
+    return elements;
+  }
+
+  /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */
+  public void testMultibinderDependenciesInToolStage() {
+    Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() {
+      @Override protected void configure() {
+          MapBinder<Integer, String> mapBinder
+              = MapBinder.newMapBinder(binder(), Integer.class, String.class);
+          mapBinder.addBinding(1).toInstance("A");
+          mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b")));
+  
+          bindConstant().annotatedWith(Names.named("b")).to("B");
+        }});
+
+    Binding<Map<Integer, String>> binding = injector.getBinding(new Key<Map<Integer, String>>() {});
+    HasDependencies withDependencies = (HasDependencies) binding;
+    Key<?> setKey = new Key<Set<Map.Entry<Integer, Provider<String>>>>() {};
+    assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(setKey)),
+        withDependencies.getDependencies());
+  }
+  
+
+  /**
+   * Our implementation maintains order, but doesn't guarantee it in the API spec.
+   * TODO: specify the iteration order?
+   */
+  public void testBindOrderEqualsIterationOrder() {
+    Injector injector = Guice.createInjector(
+        new AbstractModule() {
+          @Override protected void configure() {
+            MapBinder<String, String> mapBinder
+                = MapBinder.newMapBinder(binder(), String.class, String.class);
+            mapBinder.addBinding("leonardo").toInstance("blue");
+            mapBinder.addBinding("donatello").toInstance("purple");
+            install(new AbstractModule() {
+              @Override protected void configure() {
+                MapBinder.newMapBinder(binder(), String.class, String.class)
+                    .addBinding("michaelangelo").toInstance("orange");
+              }
+            });
+          }
+        },
+        new AbstractModule() {
+          @Override protected void configure() {
+            MapBinder.newMapBinder(binder(), String.class, String.class)
+                .addBinding("raphael").toInstance("red");
+          }
+        });
+
+    Map<String, String> map = injector.getInstance(new Key<Map<String, String>>() {});
+    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+    assertEquals(Maps.immutableEntry("leonardo", "blue"), iterator.next());
+    assertEquals(Maps.immutableEntry("donatello", "purple"), iterator.next());
+    assertEquals(Maps.immutableEntry("michaelangelo", "orange"), iterator.next());
+    assertEquals(Maps.immutableEntry("raphael", "red"), iterator.next());
+  }
+  
+  /**
+   * With overrides, we should get the union of all map bindings.
+   */
+  public void testModuleOverrideAndMapBindings() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B");
+      }
+    };
+    Module cd = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
+        multibinder.addBinding("c").toInstance("C");
+        multibinder.addBinding("d").toInstance("D");
+      }
+    };
+    Module ef = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
+        multibinder.addBinding("e").toInstance("E");
+        multibinder.addBinding("f").toInstance("F");
+      }
+    };
+
+    Module abcd = Modules.override(ab).with(cd);
+    Injector injector = Guice.createInjector(abcd, ef);
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"),
+        injector.getInstance(Key.get(mapOfString)));
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abcd, ef), BOTH, false, 0,
+        instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("d", "D"), instance(
+            "e", "E"), instance("f", "F"));
+  }
+  
+  public void testDeduplicateMapBindings() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> mapbinder =
+            MapBinder.newMapBinder(binder(), String.class, String.class);
+        mapbinder.addBinding("a").toInstance("A");
+        mapbinder.addBinding("a").toInstance("A");
+        mapbinder.addBinding("b").toInstance("B");
+        mapbinder.addBinding("b").toInstance("B");
+        
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertEquals(mapOf("a", "A", "b", "B"),
+        injector.getInstance(Key.get(mapOfString)));
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 0,
+        instance("a", "A"), instance("b", "B"));
+  }
+  
+  /**
+   * With overrides, we should get the union of all map bindings.
+   */
+  public void testModuleOverrideAndMapBindingsWithPermitDuplicates() {
+    Module abc = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B");
+        multibinder.addBinding("c").toInstance("C");
+        multibinder.permitDuplicates();
+      }
+    };
+    Module cd = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
+        multibinder.addBinding("c").toInstance("C");
+        multibinder.addBinding("d").toInstance("D");
+        multibinder.permitDuplicates();
+      }
+    };
+    Module ef = new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
+        multibinder.addBinding("e").toInstance("E");
+        multibinder.addBinding("f").toInstance("F");
+        multibinder.permitDuplicates();
+      }
+    };
+
+    Module abcd = Modules.override(abc).with(cd);
+    Injector injector = Guice.createInjector(abcd, ef);
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"),
+        injector.getInstance(Key.get(mapOfString)));
+    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abcd, ef), BOTH, true, 0,
+        instance("a", "A"), instance("b", "B"), instance("c", "C"), instance(
+            "d", "D"), instance("e", "E"), instance("f", "F"));
+
+  }  
+
+  /** Ensure there are no initialization race conditions in basic map injection. */
+  public void testBasicMapDependencyInjection() {
+    final AtomicReference<Map<String, String>> injectedMap =
+        new AtomicReference<Map<String, String>>();
+    final Object anObject = new Object() {
+      @Inject void initialize(Map<String, String> map) {
+        injectedMap.set(map);
+      }
+    };
+    Module abc = new AbstractModule() {
+      @Override protected void configure() {
+        requestInjection(anObject);
+        MapBinder<String, String> multibinder =
+            MapBinder.newMapBinder(binder(), String.class, String.class);
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B");
+        multibinder.addBinding("c").toInstance("C");
+      }
+    };
+    Guice.createInjector(abc);
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injectedMap.get());
+  } 
+
+  /** Ensure there are no initialization race conditions in provider multimap injection. */
+  public void testProviderMultimapDependencyInjection() {
+    final AtomicReference<Map<String, Set<Provider<String>>>> injectedMultimap =
+        new AtomicReference<Map<String, Set<Provider<String>>>>();
+    final Object anObject = new Object() {
+      @Inject void initialize(Map<String, Set<Provider<String>>> multimap) {
+        injectedMultimap.set(multimap);
+      }
+    };
+    Module abc = new AbstractModule() {
+      @Override protected void configure() {
+        requestInjection(anObject);
+        MapBinder<String, String> multibinder =
+            MapBinder.newMapBinder(binder(), String.class, String.class);
+        multibinder.permitDuplicates();
+        multibinder.addBinding("a").toInstance("A");
+        multibinder.addBinding("b").toInstance("B");
+        multibinder.addBinding("c").toInstance("C");
+      }
+    };
+    Guice.createInjector(abc);
+    Map<String, String> map = Maps.transformValues(injectedMultimap.get(),
+        new Function<Set<Provider<String>>, String>() {
+          @Override public String apply(Set<Provider<String>> stringProvidersSet) {
+            return Iterables.getOnlyElement(stringProvidersSet).get();
+          }
+        });
+    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), map);
+  }
+  
+  @Retention(RUNTIME) @BindingAnnotation
+  @interface Abc {}
+
+  @Retention(RUNTIME) @BindingAnnotation
+  @interface De {}
+
+  @SuppressWarnings("unchecked")
+  private <K, V> Map<K, V> mapOf(Object... elements) {
+    Map<K, V> result = new HashMap<K, V>();
+    for (int i = 0; i < elements.length; i += 2) {
+      result.put((K)elements[i], (V)elements[i+1]);
+    }
+    return result;
+  }
+
+  @SuppressWarnings("unchecked")
+  private <V> Set<V> setOf(V... elements) {
+    return new HashSet<V>(Arrays.asList(elements));
+  }
+
+  @BindingAnnotation
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
+  private static @interface Marker {}
+
+  @Marker
+  public void testMapBinderMatching() throws Exception {
+    Method m = MapBinderTest.class.getDeclaredMethod("testMapBinderMatching");
+    assertNotNull(m);
+    final Annotation marker = m.getAnnotation(Marker.class);
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override public void configure() {
+        MapBinder<Integer, Integer> mb1 =
+          MapBinder.newMapBinder(binder(), Integer.class, Integer.class, Marker.class);
+        MapBinder<Integer, Integer> mb2 = 
+          MapBinder.newMapBinder(binder(), Integer.class, Integer.class, marker);
+        mb1.addBinding(1).toInstance(1);
+        mb2.addBinding(2).toInstance(2);
+
+        // This assures us that the two binders are equivalent, so we expect the instance added to
+        // each to have been added to one set.
+        assertEquals(mb1, mb2);
+      }
+    });
+    TypeLiteral<Map<Integer, Integer>> t = new TypeLiteral<Map<Integer, Integer>>() {};
+    Map<Integer, Integer> s1 = injector.getInstance(Key.get(t, Marker.class));
+    Map<Integer, Integer> s2 = injector.getInstance(Key.get(t, marker));
+
+    // This assures us that the two sets are in fact equal.  They may not be same set (as in Java
+    // object identical), but we shouldn't expect that, since probably Guice creates the set each
+    // time in case the elements are dependent on scope.
+    assertEquals(s1, s2);
+
+    // This ensures that MultiBinder is internally using the correct set name --
+    // making sure that instances of marker annotations have the same set name as
+    // MarkerAnnotation.class.
+    Map<Integer, Integer> expected = new HashMap<Integer, Integer>();
+    expected.put(1, 1);
+    expected.put(2, 2);
+    assertEquals(expected, s1);
+  }
+
+  public void testTwoMapBindersAreDistinct() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {  
+        MapBinder.newMapBinder(binder(), String.class, String.class)
+            .addBinding("A").toInstance("a");
+        
+        MapBinder.newMapBinder(binder(), Integer.class, String.class)
+            .addBinding(1).toInstance("b");
+      }
+    });
+    Collector collector = new Collector();
+    Binding<Map<String, String>> map1 = injector.getBinding(Key.get(mapOfString));
+    map1.acceptTargetVisitor(collector);
+    assertNotNull(collector.mapbinding);
+    MapBinderBinding<?> map1Binding = collector.mapbinding;
+  
+    Binding<Map<Integer, String>> map2 = injector.getBinding(Key.get(mapOfIntString));
+    map2.acceptTargetVisitor(collector);
+    assertNotNull(collector.mapbinding);
+    MapBinderBinding<?> map2Binding = collector.mapbinding;
+  
+    List<Binding<String>> bindings = injector.findBindingsByType(stringType);
+    assertEquals("should have two elements: " + bindings, 2, bindings.size());
+    Binding<String> a = bindings.get(0);
+    Binding<String> b = bindings.get(1);
+    assertEquals("a", ((InstanceBinding<String>) a).getInstance());
+    assertEquals("b", ((InstanceBinding<String>) b).getInstance());
+    
+    // Make sure the correct elements belong to their own sets.
+    assertTrue(map1Binding.containsElement(a));
+    assertFalse(map1Binding.containsElement(b));
+  
+    assertFalse(map2Binding.containsElement(a));
+    assertTrue(map2Binding.containsElement(b));
+  }
+
+  // Tests for com.google.inject.internal.WeakKeySet not leaking memory.
+  public void testWeakKeySet_integration_mapbinder() {
+    Key<Map<String, String>> mapKey = Key.get(new TypeLiteral<Map<String, String>>() {});
+    
+    Injector parentInjector = Guice.createInjector(new AbstractModule() {
+          @Override protected void configure() {
+            bind(String.class).toInstance("hi");
+          }
+        });
+    WeakKeySetUtils.assertNotBlacklisted(parentInjector, mapKey);
+
+    Injector childInjector = parentInjector.createChildInjector(new AbstractModule() {
+      @Override protected void configure() {
+        MapBinder<String, String> binder =
+            MapBinder.newMapBinder(binder(), String.class, String.class);
+        binder.addBinding("bar").toInstance("foo");
+      }
+    });
+    WeakReference<Injector> weakRef = new WeakReference<Injector>(childInjector);
+    WeakKeySetUtils.assertBlacklisted(parentInjector, mapKey);
+    
+    // Clear the ref, GC, and ensure that we are no longer blacklisting.
+    childInjector = null;
+    
+    Asserts.awaitClear(weakRef);
+    WeakKeySetUtils.assertNotBlacklisted(parentInjector, mapKey);
+  }
+}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
new file mode 100644
index 0000000..154779d
--- /dev/null
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
@@ -0,0 +1,1221 @@
+/**
+ * Copyright (C) 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.inject.multibindings;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.multibindings.Multibinder.collectionOfJavaxProvidersOf;
+import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH;
+import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE;
+import static com.google.inject.multibindings.SpiUtils.assertSetVisitor;
+import static com.google.inject.multibindings.SpiUtils.instance;
+import static com.google.inject.multibindings.SpiUtils.providerInstance;
+import static com.google.inject.name.Names.named;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicates;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+import com.google.inject.Scopes;
+import com.google.inject.Stage;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.LinkedKeyBinding;
+import com.google.inject.util.Modules;
+import com.google.inject.util.Providers;
+import com.google.inject.util.Types;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class MultibinderTest extends TestCase {
+
+  final TypeLiteral<Optional<String>> optionalOfString =
+      new TypeLiteral<Optional<String>>() {};
+  final TypeLiteral<Map<String, String>> mapOfStringString =
+      new TypeLiteral<Map<String, String>>() {};
+  final TypeLiteral<Set<String>> setOfString = new TypeLiteral<Set<String>>() {};
+  final TypeLiteral<Set<Integer>> setOfInteger = new TypeLiteral<Set<Integer>>() {};
+  final TypeLiteral<String> stringType = TypeLiteral.get(String.class);
+  final TypeLiteral<Integer> intType = TypeLiteral.get(Integer.class);
+  final TypeLiteral<List<String>> listOfStrings = new TypeLiteral<List<String>>() {};
+  final TypeLiteral<Set<List<String>>> setOfListOfStrings = new TypeLiteral<Set<List<String>>>() {};
+  final TypeLiteral<Collection<Provider<String>>> collectionOfProvidersOfStrings =
+      new TypeLiteral<Collection<Provider<String>>>() {};
+
+  public void testMultibinderAggregatesMultipleModules() {
+    Module abc = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().toInstance("B");
+        multibinder.addBinding().toInstance("C");
+      }
+    };
+    Module de = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("D");
+        multibinder.addBinding().toInstance("E");
+      }
+    };
+
+    Injector injector = Guice.createInjector(abc, de);
+    Key<Set<String>> setKey = Key.get(setOfString);
+    Set<String> abcde = injector.getInstance(setKey);
+    Set<String> results = setOf("A", "B", "C", "D", "E");
+
+    assertEquals(results, abcde);
+    assertSetVisitor(setKey, stringType, setOf(abc, de), BOTH, false, 0,
+        instance("A"), instance("B"), instance("C"), instance("D"), instance("E"));
+  }
+
+  public void testMultibinderAggregationForAnnotationInstance() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder
+            = Multibinder.newSetBinder(binder(), String.class, Names.named("abc"));
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().toInstance("B");
+
+        multibinder = Multibinder.newSetBinder(binder(), String.class, Names.named("abc"));
+        multibinder.addBinding().toInstance("C");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Key<Set<String>> setKey = Key.get(setOfString, Names.named("abc"));
+    Set<String> abc = injector.getInstance(setKey);
+    Set<String> results = setOf("A", "B", "C");
+    assertEquals(results, abc);
+    assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0,
+        instance("A"), instance("B"), instance("C"));
+  }
+
+  public void testMultibinderAggregationForAnnotationType() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder
+            = Multibinder.newSetBinder(binder(), String.class, Abc.class);
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().toInstance("B");
+
+        multibinder = Multibinder.newSetBinder(binder(), String.class, Abc.class);
+        multibinder.addBinding().toInstance("C");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Key<Set<String>> setKey = Key.get(setOfString, Abc.class);
+    Set<String> abcde = injector.getInstance(setKey);
+    Set<String> results = setOf("A", "B", "C");
+    assertEquals(results, abcde);
+    assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0,
+        instance("A"), instance("B"), instance("C"));
+  }
+
+  public void testMultibinderWithMultipleAnnotationValueSets() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> abcMultibinder
+            = Multibinder.newSetBinder(binder(), String.class, named("abc"));
+        abcMultibinder.addBinding().toInstance("A");
+        abcMultibinder.addBinding().toInstance("B");
+        abcMultibinder.addBinding().toInstance("C");
+
+        Multibinder<String> deMultibinder
+            = Multibinder.newSetBinder(binder(), String.class, named("de"));
+        deMultibinder.addBinding().toInstance("D");
+        deMultibinder.addBinding().toInstance("E");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Key<Set<String>> abcSetKey = Key.get(setOfString, named("abc"));
+    Set<String> abc = injector.getInstance(abcSetKey);
+    Key<Set<String>> deSetKey = Key.get(setOfString, named("de"));
+    Set<String> de = injector.getInstance(deSetKey);
+    Set<String> abcResults = setOf("A", "B", "C");
+    assertEquals(abcResults, abc);
+    Set<String> deResults = setOf("D", "E");
+    assertEquals(deResults, de);
+    assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1,
+        instance("A"), instance("B"), instance("C"));
+    assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1,
+        instance("D"), instance("E"));
+  }
+
+  public void testMultibinderWithMultipleAnnotationTypeSets() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> abcMultibinder
+            = Multibinder.newSetBinder(binder(), String.class, Abc.class);
+        abcMultibinder.addBinding().toInstance("A");
+        abcMultibinder.addBinding().toInstance("B");
+        abcMultibinder.addBinding().toInstance("C");
+
+        Multibinder<String> deMultibinder
+            = Multibinder.newSetBinder(binder(), String.class, De.class);
+        deMultibinder.addBinding().toInstance("D");
+        deMultibinder.addBinding().toInstance("E");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Key<Set<String>> abcSetKey = Key.get(setOfString, Abc.class);
+    Set<String> abc = injector.getInstance(abcSetKey);
+    Key<Set<String>> deSetKey = Key.get(setOfString, De.class);
+    Set<String> de = injector.getInstance(deSetKey);
+    Set<String> abcResults = setOf("A", "B", "C");
+    assertEquals(abcResults, abc);
+    Set<String> deResults = setOf("D", "E");
+    assertEquals(deResults, de);
+    assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1,
+        instance("A"), instance("B"), instance("C"));
+    assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1,
+        instance("D"), instance("E"));
+  }
+
+  public void testMultibinderWithMultipleSetTypes() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder.newSetBinder(binder(), String.class)
+            .addBinding().toInstance("A");
+        Multibinder.newSetBinder(binder(), Integer.class)
+            .addBinding().toInstance(1);
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(setOf("A"), injector.getInstance(Key.get(setOfString)));
+    assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger)));
+    assertSetVisitor(Key.get(setOfString), stringType, setOf(module), BOTH, false, 1,
+        instance("A"));
+    assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 1,
+        instance(1));
+  }
+
+  public void testMultibinderWithEmptySet() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder.newSetBinder(binder(), String.class);
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Set<String> set = injector.getInstance(Key.get(setOfString));
+    assertEquals(Collections.emptySet(), set);
+    assertSetVisitor(Key.get(setOfString), stringType,
+        setOf(module), BOTH, false, 0);
+  }
+
+  public void testMultibinderSetIsUnmodifiable() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder.newSetBinder(binder(), String.class)
+            .addBinding().toInstance("A");
+      }
+    });
+
+    Set<String> set = injector.getInstance(Key.get(setOfString));
+    try {
+      set.clear();
+      fail();
+    } catch(UnsupportedOperationException expected) {
+    }
+  }
+
+  public void testMultibinderSetIsSerializable() throws IOException, ClassNotFoundException {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder.newSetBinder(binder(), String.class)
+            .addBinding().toInstance("A");
+      }
+    });
+
+    Set<String> set = injector.getInstance(Key.get(setOfString));
+    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+    ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream);
+    try {
+      objectOutputStream.writeObject(set);
+    } finally {
+      objectOutputStream.close();
+    }
+    ObjectInputStream objectInputStream = new ObjectInputStream(
+        new ByteArrayInputStream(byteStream.toByteArray()));
+    try {
+      Object setCopy = objectInputStream.readObject();
+      assertEquals(set, setCopy);
+    } finally {
+      objectInputStream.close();
+    }
+  }
+
+  public void testMultibinderSetIsLazy() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder.newSetBinder(binder(), Integer.class)
+            .addBinding().toProvider(new Provider<Integer>() {
+          int nextValue = 1;
+          public Integer get() {
+            return nextValue++;
+          }
+        });
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger)));
+    assertEquals(setOf(2), injector.getInstance(Key.get(setOfInteger)));
+    assertEquals(setOf(3), injector.getInstance(Key.get(setOfInteger)));
+    assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 0,
+        providerInstance(1));
+  }
+
+  public void testMultibinderSetForbidsDuplicateElements() {
+    Module module1 = new AbstractModule() {
+      @Override protected void configure() {
+        final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toProvider(Providers.of("A"));
+      }
+    };
+    Module module2 = new AbstractModule() {
+      @Override protected void configure() {
+        final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("A");
+      }
+    };
+    Injector injector = Guice.createInjector(module1, module2);
+
+    try {
+      injector.getInstance(Key.get(setOfString));
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "1) Set injection failed due to duplicated element \"A\"",
+          "Bound at " + module1.getClass().getName(),
+          "Bound at " + module2.getClass().getName());
+    }
+
+    // But we can still visit the module!
+    assertSetVisitor(Key.get(setOfString), stringType, setOf(module1, module2), MODULE, false, 0,
+        instance("A"), instance("A"));
+  }
+
+  public void testMultibinderSetShowsBothElementsIfToStringDifferent() {
+    // A simple example of a type whose toString returns more information than its equals method
+    // considers.
+    class ValueType {
+      int a;
+      int b;
+      ValueType(int a, int b) {
+        this.a = a;
+        this.b = b;
+      }
+      @Override
+      public boolean equals(Object obj) {
+        return (obj instanceof ValueType) && (((ValueType) obj).a == a);
+      }
+      @Override
+      public int hashCode() {
+        return a;
+      }
+      @Override
+      public String toString() {
+        return String.format("ValueType(%d,%d)", a, b);
+      }
+    }
+
+    Module module1 = new AbstractModule() {
+      @Override protected void configure() {
+        final Multibinder<ValueType> multibinder =
+            Multibinder.newSetBinder(binder(), ValueType.class);
+        multibinder.addBinding().toProvider(Providers.of(new ValueType(1, 2)));
+      }
+    };
+    Module module2 = new AbstractModule() {
+      @Override protected void configure() {
+        final Multibinder<ValueType> multibinder =
+            Multibinder.newSetBinder(binder(), ValueType.class);
+        multibinder.addBinding().toInstance(new ValueType(1, 3));
+      }
+    };
+    Injector injector = Guice.createInjector(module1, module2);
+
+    TypeLiteral<ValueType> valueType = TypeLiteral.get(ValueType.class);
+    TypeLiteral<Set<ValueType>> setOfValueType = new TypeLiteral<Set<ValueType>>() {};
+    try {
+      injector.getInstance(Key.get(setOfValueType));
+      fail();
+    } catch (ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "1) Set injection failed due to multiple elements comparing equal:",
+          "\"ValueType(1,2)\"",
+          "bound at " + module1.getClass().getName(),
+          "\"ValueType(1,3)\"",
+          "bound at " + module2.getClass().getName());
+    }
+
+    // But we can still visit the module!
+    assertSetVisitor(Key.get(setOfValueType), valueType, setOf(module1, module2), MODULE, false, 0,
+        instance(new ValueType(1, 2)), instance(new ValueType(1, 3)));
+  }
+
+  public void testMultibinderSetPermitDuplicateElements() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().toInstance("B");
+      }
+    };
+    Module bc = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.permitDuplicates();
+        multibinder.addBinding().toInstance("B");
+        multibinder.addBinding().toInstance("C");
+      }
+    };
+    Injector injector = Guice.createInjector(ab, bc);
+
+    assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString)));
+    assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0,
+        instance("A"), instance("B"), instance("C"));
+  }
+
+  public void testMultibinderSetPermitDuplicateCallsToPermitDuplicates() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.permitDuplicates();
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().toInstance("B");
+      }
+    };
+    Module bc = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.permitDuplicates();
+        multibinder.addBinding().toInstance("B");
+        multibinder.addBinding().toInstance("C");
+      }
+    };
+    Injector injector = Guice.createInjector(ab, bc);
+
+    assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString)));
+    assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0,
+        instance("A"), instance("B"), instance("C"));
+  }
+
+  public void testMultibinderSetForbidsNullElements() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder.newSetBinder(binder(), String.class)
+            .addBinding().toProvider(Providers.<String>of(null));
+      }
+    };
+    Injector injector = Guice.createInjector(m);
+
+    try {
+      injector.getInstance(Key.get(setOfString));
+      fail();
+    } catch(ProvisionException expected) {
+      assertContains(expected.getMessage(),
+          "1) Set injection failed due to null element bound at: "
+          + m.getClass().getName() + ".configure(");
+    }
+  }
+
+  public void testSourceLinesInMultibindings() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          Multibinder.newSetBinder(binder(), Integer.class).addBinding();
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "No implementation for java.lang.Integer",
+          "at " + getClass().getName());
+    }
+  }
+
+  /**
+   * We just want to make sure that multibinder's binding depends on each of its values. We don't
+   * really care about the underlying structure of those bindings, which are implementation details.
+   */
+  public void testMultibinderDependencies() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().to(Key.get(String.class, Names.named("b")));
+
+        bindConstant().annotatedWith(Names.named("b")).to("B");
+      }
+    });
+
+    Binding<Set<String>> binding = injector.getBinding(new Key<Set<String>>() {});
+    HasDependencies withDependencies = (HasDependencies) binding;
+    Set<String> elements = Sets.newHashSet();
+    for (Dependency<?> dependency : withDependencies.getDependencies()) {
+      elements.add((String) injector.getInstance(dependency.getKey()));
+    }
+    assertEquals(ImmutableSet.of("A", "B"), elements);
+  }
+
+  /**
+   * We just want to make sure that multibinder's binding depends on each of its values. We don't
+   * really care about the underlying structure of those bindings, which are implementation details.
+   */
+  public void testMultibinderDependenciesInToolStage() {
+    Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().to(Key.get(String.class, Names.named("b")));
+
+        bindConstant().annotatedWith(Names.named("b")).to("B");
+      }
+    });
+
+    Binding<Set<String>> binding = injector.getBinding(new Key<Set<String>>() {});
+    HasDependencies withDependencies = (HasDependencies) binding;
+    InstanceBinding<?> instanceBinding = null;
+    LinkedKeyBinding<?> linkedBinding = null;
+    // The non-tool stage test can test this by calling injector.getInstance to ensure
+    // the right values are returned -- in tool stage we can't do that.  It's also a
+    // little difficult to validate the dependencies & bindings, because they're
+    // bindings created internally within Multibinder.
+    // To workaround this, we just validate that the dependencies lookup to a single
+    // InstanceBinding whose value is "A" and another LinkedBinding whose target is
+    // the Key of @Named("b") String=B
+    for (Dependency<?> dependency : withDependencies.getDependencies()) {
+      Binding<?> b = injector.getBinding(dependency.getKey());
+      if(b instanceof InstanceBinding) {
+        if(instanceBinding != null) {
+          fail("Already have an instance binding of: " + instanceBinding + ", and now want to add: " + b);
+        } else {
+          instanceBinding = (InstanceBinding)b;
+        }
+      } else if(b instanceof LinkedKeyBinding) {
+        if(linkedBinding != null) {
+          fail("Already have a linked binding of: " + linkedBinding + ", and now want to add: " + b);
+        } else {
+          linkedBinding = (LinkedKeyBinding)b;
+        }
+      } else {
+        fail("Unexpected dependency of: " + dependency);
+      }
+    }
+
+    assertNotNull(instanceBinding);
+    assertNotNull(linkedBinding);
+
+    assertEquals("A", instanceBinding.getInstance());
+    assertEquals(Key.get(String.class, Names.named("b")), linkedBinding.getLinkedKey());
+  }
+
+  /**
+   * Our implementation maintains order, but doesn't guarantee it in the API spec.
+   * TODO: specify the iteration order?
+   */
+  public void testBindOrderEqualsIterationOrder() {
+    Injector injector = Guice.createInjector(
+        new AbstractModule() {
+          @Override protected void configure() {
+            Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+            multibinder.addBinding().toInstance("leonardo");
+            multibinder.addBinding().toInstance("donatello");
+            install(new AbstractModule() {
+              @Override protected void configure() {
+                Multibinder.newSetBinder(binder(), String.class)
+                    .addBinding().toInstance("michaelangelo");
+              }
+            });
+          }
+        },
+        new AbstractModule() {
+          @Override protected void configure() {
+            Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("raphael");
+          }
+        });
+
+    List<String> inOrder = ImmutableList.copyOf(injector.getInstance(Key.get(setOfString)));
+    assertEquals(ImmutableList.of("leonardo", "donatello", "michaelangelo", "raphael"), inOrder);
+  }
+
+  @Retention(RUNTIME) @BindingAnnotation
+  @interface Abc {}
+
+  @Retention(RUNTIME) @BindingAnnotation
+  @interface De {}
+
+  private <T> Set<T> setOf(T... elements) {
+    Set<T> result = Sets.newHashSet();
+    Collections.addAll(result, elements);
+    return result;
+  }
+
+  /**
+   * With overrides, we should get the union of all multibindings.
+   */
+  public void testModuleOverrideAndMultibindings() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().toInstance("B");
+      }
+    };
+    Module cd = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("C");
+        multibinder.addBinding().toInstance("D");
+      }
+    };
+    Module ef = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("E");
+        multibinder.addBinding().toInstance("F");
+      }
+    };
+
+    Module abcd = Modules.override(ab).with(cd);
+    Injector injector = Guice.createInjector(abcd, ef);
+    assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"),
+        injector.getInstance(Key.get(setOfString)));
+
+    assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, false, 0,
+        instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F"));
+  }
+
+  /**
+   * With overrides, we should get the union of all multibindings.
+   */
+  public void testModuleOverrideAndMultibindingsWithPermitDuplicates() {
+    Module abc = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().toInstance("B");
+        multibinder.addBinding().toInstance("C");
+        multibinder.permitDuplicates();
+      }
+    };
+    Module cd = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("C");
+        multibinder.addBinding().toInstance("D");
+        multibinder.permitDuplicates();
+      }
+    };
+    Module ef = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("E");
+        multibinder.addBinding().toInstance("F");
+        multibinder.permitDuplicates();
+      }
+    };
+
+    Module abcd = Modules.override(abc).with(cd);
+    Injector injector = Guice.createInjector(abcd, ef);
+    assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"),
+        injector.getInstance(Key.get(setOfString)));
+
+    assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, true, 0,
+        instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F"));
+  }
+
+  /**
+   * Doubly-installed modules should not conflict, even when one is overridden.
+   */
+  public void testModuleOverrideRepeatedInstallsAndMultibindings_toInstance() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toInstance("A");
+        multibinder.addBinding().toInstance("B");
+      }
+    };
+
+    // Guice guarantees this assertion, as the same module cannot be installed twice.
+    assertEquals(ImmutableSet.of("A", "B"),
+        Guice.createInjector(ab, ab).getInstance(Key.get(setOfString)));
+
+    // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
+    Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
+    assertEquals(ImmutableSet.of("A", "B"),
+        injector.getInstance(Key.get(setOfString)));
+  }
+
+  public void testModuleOverrideRepeatedInstallsAndMultibindings_toKey() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Key<String> aKey = Key.get(String.class, Names.named("A_string"));
+        Key<String> bKey = Key.get(String.class, Names.named("B_string"));
+        bind(aKey).toInstance("A");
+        bind(bKey).toInstance("B");
+
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().to(aKey);
+        multibinder.addBinding().to(bKey);
+      }
+    };
+
+    // Guice guarantees this assertion, as the same module cannot be installed twice.
+    assertEquals(ImmutableSet.of("A", "B"),
+        Guice.createInjector(ab, ab).getInstance(Key.get(setOfString)));
+
+    // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
+    Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
+    assertEquals(ImmutableSet.of("A", "B"),
+        injector.getInstance(Key.get(setOfString)));
+  }
+
+  public void testModuleOverrideRepeatedInstallsAndMultibindings_toProviderInstance() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toProvider(Providers.of("A"));
+        multibinder.addBinding().toProvider(Providers.of("B"));
+      }
+    };
+
+    // Guice guarantees this assertion, as the same module cannot be installed twice.
+    assertEquals(ImmutableSet.of("A", "B"),
+        Guice.createInjector(ab, ab).getInstance(Key.get(setOfString)));
+
+    // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
+    Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
+    assertEquals(ImmutableSet.of("A", "B"),
+        injector.getInstance(Key.get(setOfString)));
+  }
+
+  private static class AStringProvider implements Provider<String> {
+    public String get() {
+      return "A";
+    }
+  }
+
+  private static class BStringProvider implements Provider<String> {
+    public String get() {
+      return "B";
+    }
+  }
+
+  public void testModuleOverrideRepeatedInstallsAndMultibindings_toProviderKey() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toProvider(Key.get(AStringProvider.class));
+        multibinder.addBinding().toProvider(Key.get(BStringProvider.class));
+      }
+    };
+
+    // Guice guarantees this assertion, as the same module cannot be installed twice.
+    assertEquals(ImmutableSet.of("A", "B"),
+        Guice.createInjector(ab, ab).getInstance(Key.get(setOfString)));
+
+    // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
+    Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
+    assertEquals(ImmutableSet.of("A", "B"),
+        injector.getInstance(Key.get(setOfString)));
+  }
+
+  private static class StringGrabber {
+    private final String string;
+
+    @SuppressWarnings("unused")  // Found by reflection
+    public StringGrabber(@Named("A_string") String string) {
+      this.string = string;
+    }
+
+    @SuppressWarnings("unused")  // Found by reflection
+    public StringGrabber(@Named("B_string") String string, int unused) {
+      this.string = string;
+    }
+
+    @Override
+    public int hashCode() {
+      return string.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string);
+    }
+
+    @Override
+    public String toString() {
+      return "StringGrabber(" + string + ")";
+    }
+
+    static Set<String> values(Iterable<StringGrabber> grabbers) {
+      Set<String> result = new HashSet<String>();
+      for (StringGrabber grabber : grabbers) {
+        result.add(grabber.string);
+      }
+      return result;
+    }
+  }
+
+  public void testModuleOverrideRepeatedInstallsAndMultibindings_toConstructor() {
+    TypeLiteral<Set<StringGrabber>> setOfStringGrabber = new TypeLiteral<Set<StringGrabber>>() {};
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Key<String> aKey = Key.get(String.class, Names.named("A_string"));
+        Key<String> bKey = Key.get(String.class, Names.named("B_string"));
+        bind(aKey).toInstance("A");
+        bind(bKey).toInstance("B");
+        bind(Integer.class).toInstance(0);  // used to disambiguate constructors
+
+        Multibinder<StringGrabber> multibinder =
+            Multibinder.newSetBinder(binder(), StringGrabber.class);
+        try {
+          multibinder.addBinding().toConstructor(
+              StringGrabber.class.getConstructor(String.class));
+          multibinder.addBinding().toConstructor(
+              StringGrabber.class.getConstructor(String.class, int.class));
+        } catch (NoSuchMethodException e) {
+          fail("No such method: " + e.getMessage());
+        }
+      }
+    };
+
+    // Guice guarantees this assertion, as the same module cannot be installed twice.
+    assertEquals(ImmutableSet.of("A", "B"),
+        StringGrabber.values(
+            Guice.createInjector(ab, ab).getInstance(Key.get(setOfStringGrabber))));
+
+    // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
+    Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
+    assertEquals(ImmutableSet.of("A", "B"),
+        StringGrabber.values(injector.getInstance(Key.get(setOfStringGrabber))));
+  }
+
+  /**
+   * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or
+   * explicitly bound in {@link Scopes#NO_SCOPE}.
+   */
+  public void testDuplicateUnscopedBindings() {
+    Module singleBinding = new AbstractModule() {
+      @Override protected void configure() {
+        bind(Integer.class).to(Key.get(Integer.class, named("A")));
+        bind(Integer.class).to(Key.get(Integer.class, named("A"))).in(Scopes.NO_SCOPE);
+      }
+
+      @Provides @Named("A")
+      int provideInteger() {
+        return 5;
+      }
+    };
+    Module multibinding = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<Integer> multibinder = Multibinder.newSetBinder(binder(), Integer.class);
+        multibinder.addBinding().to(Key.get(Integer.class, named("A")));
+        multibinder.addBinding().to(Key.get(Integer.class, named("A"))).in(Scopes.NO_SCOPE);
+      }
+    };
+
+    assertEquals(5,
+        (int) Guice.createInjector(singleBinding).getInstance(Integer.class));
+    assertEquals(ImmutableSet.of(5),
+        Guice.createInjector(singleBinding, multibinding).getInstance(Key.get(setOfInteger)));
+  }
+
+  /**
+   * Ensure key hash codes are fixed at injection time, not binding time.
+   */
+  public void testKeyHashCodesFixedAtInjectionTime() {
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<List<String>> multibinder = Multibinder.newSetBinder(binder(), listOfStrings);
+        List<String> list = Lists.newArrayList();
+        multibinder.addBinding().toInstance(list);
+        list.add("A");
+        list.add("B");
+      }
+    };
+
+    Injector injector = Guice.createInjector(ab);
+    for (Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
+      Key<?> bindingKey = entry.getKey();
+      Key<?> clonedKey;
+      if (bindingKey.getAnnotation() != null) {
+        clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation());
+      } else if (bindingKey.getAnnotationType() != null) {
+        clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType());
+      } else {
+        clonedKey = Key.get(bindingKey.getTypeLiteral());
+      }
+      assertEquals(bindingKey, clonedKey);
+      assertEquals("Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(),
+          bindingKey.hashCode(), clonedKey.hashCode());
+    }
+  }
+
+  /**
+   * Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}.
+   */
+  public void testBindingKeysFixedOnReturnFromGetElements() {
+    final List<String> list = Lists.newArrayList();
+    Module ab = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<List<String>> multibinder = Multibinder.newSetBinder(binder(), listOfStrings);
+        multibinder.addBinding().toInstance(list);
+        list.add("A");
+        list.add("B");
+      }
+    };
+
+    InstanceBinding<?> binding = Iterables.getOnlyElement(
+        Iterables.filter(Elements.getElements(ab), InstanceBinding.class));
+    Key<?> keyBefore = binding.getKey();
+    assertEquals(listOfStrings, keyBefore.getTypeLiteral());
+
+    list.add("C");
+    Key<?> keyAfter = binding.getKey();
+    assertSame(keyBefore, keyAfter);
+  }
+
+  /*
+   * Verify through gratuitous mutation that key hashCode snapshots and whatnot happens at the right
+   * times, by binding two lists that are different at injector creation, but compare equal when the
+   * module is configured *and* when the set is instantiated.
+   */
+  public void testConcurrentMutation_bindingsDiffentAtInjectorCreation() {
+    // We initially bind two equal lists
+    final List<String> list1 = Lists.newArrayList();
+    final List<String> list2 = Lists.newArrayList();
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<List<String>> multibinder = Multibinder.newSetBinder(binder(), listOfStrings);
+        multibinder.addBinding().toInstance(list1);
+        multibinder.addBinding().toInstance(list2);
+      }
+    };
+    List<Element> elements = Elements.getElements(module);
+
+    // Now we change the lists so they no longer match, and create the injector.
+    list1.add("A");
+    list2.add("B");
+    Injector injector = Guice.createInjector(Elements.getModule(elements));
+
+    // Now we change the lists so they compare equal again, and create the set.
+    list1.add(1, "B");
+    list2.add(0, "A");
+    try {
+      injector.getInstance(Key.get(setOfListOfStrings));
+      fail();
+    } catch (ProvisionException e) {
+      assertEquals(1, e.getErrorMessages().size());
+      assertContains(
+          Iterables.getOnlyElement(e.getErrorMessages()).getMessage().toString(),
+          "Set injection failed due to duplicated element \"[A, B]\"");
+    }
+
+    // Finally, we change the lists again so they are once more different, and ensure the set
+    // contains both.
+    list1.remove("A");
+    list2.remove("B");
+    Set<List<String>> set = injector.getInstance(Key.get(setOfListOfStrings));
+    assertEquals(ImmutableSet.of(ImmutableList.of("A"), ImmutableList.of("B")), set);
+  }
+
+  /*
+   * Verify through gratuitous mutation that key hashCode snapshots and whatnot happen at the right
+   * times, by binding two lists that compare equal at injector creation, but are different when the
+   * module is configured *and* when the set is instantiated.
+   */
+  public void testConcurrentMutation_bindingsSameAtInjectorCreation() {
+    // We initially bind two distinct lists
+    final List<String> list1 = Lists.newArrayList("A");
+    final List<String> list2 = Lists.newArrayList("B");
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder<List<String>> multibinder = Multibinder.newSetBinder(binder(), listOfStrings);
+        multibinder.addBinding().toInstance(list1);
+        multibinder.addBinding().toInstance(list2);
+      }
+    };
+    List<Element> elements = Elements.getElements(module);
+
+    // Now we change the lists so they compare equal, and create the injector.
+    list1.add(1, "B");
+    list2.add(0, "A");
+    Injector injector = Guice.createInjector(Elements.getModule(elements));
+
+    // Now we change the lists again so they are once more different, and create the set.
+    list1.remove("A");
+    list2.remove("B");
+    Set<List<String>> set = injector.getInstance(Key.get(setOfListOfStrings));
+
+    // The set will contain just one of the two lists.
+    // (In fact, it will be the first one we bound, but we don't promise that, so we won't test it.)
+    assertTrue(ImmutableSet.of(ImmutableList.of("A")).equals(set)
+        || ImmutableSet.of(ImmutableList.of("B")).equals(set));
+  }
+
+  @BindingAnnotation
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
+  private static @interface Marker {}
+
+  @Marker
+  public void testMultibinderMatching() throws Exception {
+    Method m = MultibinderTest.class.getDeclaredMethod("testMultibinderMatching");
+    assertNotNull(m);
+    final Annotation marker = m.getAnnotation(Marker.class);
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override public void configure() {
+        Multibinder<Integer> mb1 = Multibinder.newSetBinder(binder(), Integer.class, Marker.class);
+        Multibinder<Integer> mb2 = Multibinder.newSetBinder(binder(), Integer.class, marker);
+        mb1.addBinding().toInstance(1);
+        mb2.addBinding().toInstance(2);
+
+        // This assures us that the two binders are equivalent, so we expect the instance added to
+        // each to have been added to one set.
+        assertEquals(mb1, mb2);
+      }
+    });
+    TypeLiteral<Set<Integer>> t = new TypeLiteral<Set<Integer>>() {};
+    Set<Integer> s1 = injector.getInstance(Key.get(t, Marker.class));
+    Set<Integer> s2 = injector.getInstance(Key.get(t, marker));
+
+    // This assures us that the two sets are in fact equal.  They may not be same set (as in Java
+    // object identical), but we shouldn't expect that, since probably Guice creates the set each
+    // time in case the elements are dependent on scope.
+    assertEquals(s1, s2);
+
+    // This ensures that MultiBinder is internally using the correct set name --
+    // making sure that instances of marker annotations have the same set name as
+    // MarkerAnnotation.class.
+    Set<Integer> expected = new HashSet<Integer>();
+    expected.add(1);
+    expected.add(2);
+    assertEquals(expected, s1);
+  }
+
+  // See issue 670
+  public void testSetAndMapValueAreDistinct() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder.newSetBinder(binder(), String.class)
+            .addBinding().toInstance("A");
+
+        MapBinder.newMapBinder(binder(), String.class, String.class)
+            .addBinding("B").toInstance("b");
+
+        OptionalBinder.newOptionalBinder(binder(), String.class)
+            .setDefault().toInstance("C");
+        OptionalBinder.newOptionalBinder(binder(), String.class)
+            .setBinding().toInstance("D");
+      }
+    });
+
+    assertEquals(ImmutableSet.of("A"), injector.getInstance(Key.get(setOfString)));
+    assertEquals(ImmutableMap.of("B", "b"), injector.getInstance(Key.get(mapOfStringString)));
+    assertEquals(Optional.of("D"), injector.getInstance(Key.get(optionalOfString)));
+  }
+
+  // See issue 670
+  public void testSetAndMapValueAreDistinctInSpi() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        Multibinder.newSetBinder(binder(), String.class)
+            .addBinding().toInstance("A");
+
+        MapBinder.newMapBinder(binder(), String.class, String.class)
+            .addBinding("B").toInstance("b");
+        
+        OptionalBinder.newOptionalBinder(binder(), String.class)
+            .setDefault().toInstance("C");
+      }
+    });
+    Collector collector = new Collector();
+    Binding<Map<String, String>> mapbinding = injector.getBinding(Key.get(mapOfStringString));
+    mapbinding.acceptTargetVisitor(collector);
+    assertNotNull(collector.mapbinding);
+
+    Binding<Set<String>> setbinding = injector.getBinding(Key.get(setOfString));
+    setbinding.acceptTargetVisitor(collector);
+    assertNotNull(collector.setbinding);
+
+    Binding<Optional<String>> optionalbinding = injector.getBinding(Key.get(optionalOfString));
+    optionalbinding.acceptTargetVisitor(collector);
+    assertNotNull(collector.optionalbinding);
+
+    // There should only be three instance bindings for string types
+    // (but because of the OptionalBinder, there's 2 ProviderInstanceBindings also).
+    // We also know the InstanceBindings will be in the order: A, b, C because that's
+    // how we bound them, and binding order is preserved.
+    List<Binding<String>> bindings = FluentIterable.from(injector.findBindingsByType(stringType))
+        .filter(Predicates.instanceOf(InstanceBinding.class))
+        .toList();
+    assertEquals(bindings.toString(), 3, bindings.size());
+    Binding<String> a = bindings.get(0);
+    Binding<String> b = bindings.get(1);
+    Binding<String> c = bindings.get(2);
+    assertEquals("A", ((InstanceBinding<String>) a).getInstance());
+    assertEquals("b", ((InstanceBinding<String>) b).getInstance());
+    assertEquals("C", ((InstanceBinding<String>) c).getInstance());
+
+    // Make sure the correct elements belong to their own sets.
+    assertFalse(collector.mapbinding.containsElement(a));
+    assertTrue(collector.mapbinding.containsElement(b));
+    assertFalse(collector.mapbinding.containsElement(c));
+
+    assertTrue(collector.setbinding.containsElement(a));
+    assertFalse(collector.setbinding.containsElement(b));
+    assertFalse(collector.setbinding.containsElement(c));
+
+    assertFalse(collector.optionalbinding.containsElement(a));
+    assertFalse(collector.optionalbinding.containsElement(b));
+    assertTrue(collector.optionalbinding.containsElement(c));
+  }
+
+  public void testMultibinderCanInjectCollectionOfProviders() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+        multibinder.addBinding().toProvider(Providers.of("A"));
+        multibinder.addBinding().toProvider(Providers.of("B"));
+        multibinder.addBinding().toInstance("C");
+      }
+    };
+    Collection<String> expectedValues = ImmutableList.of("A", "B", "C");
+
+    Injector injector = Guice.createInjector(module);
+
+    Collection<Provider<String>> providers =
+        injector.getInstance(Key.get(collectionOfProvidersOfStrings));
+    assertEquals(expectedValues, collectValues(providers));
+
+    Collection<javax.inject.Provider<String>> javaxProviders =
+        injector.getInstance(Key.get(collectionOfJavaxProvidersOf(stringType)));
+    assertEquals(expectedValues, collectValues(javaxProviders));
+  }
+
+  public void testMultibinderCanInjectCollectionOfProvidersWithAnnotation() {
+    final Annotation ann = Names.named("foo");
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        final Multibinder<String> multibinder =
+            Multibinder.newSetBinder(binder(), String.class, ann);
+        multibinder.addBinding().toProvider(Providers.of("A"));
+        multibinder.addBinding().toProvider(Providers.of("B"));
+        multibinder.addBinding().toInstance("C");
+      }
+    };
+    Collection<String> expectedValues = ImmutableList.of("A", "B", "C");
+
+    Injector injector = Guice.createInjector(module);
+
+    Collection<Provider<String>> providers =
+        injector.getInstance(Key.get(collectionOfProvidersOfStrings, ann));
+    Collection<String> values = collectValues(providers);
+    assertEquals(expectedValues, values);
+
+    Collection<javax.inject.Provider<String>> javaxProviders =
+        injector.getInstance(Key.get(collectionOfJavaxProvidersOf(stringType), ann));
+    assertEquals(expectedValues, collectValues(javaxProviders));
+  }
+
+  public void testMultibindingProviderDependencies() {
+    final Annotation setAnn = Names.named("foo");
+    Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          Multibinder<String> multibinder =
+              Multibinder.newSetBinder(binder(), String.class, setAnn);
+          multibinder.addBinding().toInstance("a");
+          multibinder.addBinding().toInstance("b");
+        }
+      });
+    HasDependencies providerBinding =
+      (HasDependencies) injector.getBinding(new Key<Collection<Provider<String>>>(setAnn) {});
+    HasDependencies setBinding =
+      (HasDependencies) injector.getBinding(new Key<Set<String>>(setAnn) {});
+    // sanity check the size
+    assertEquals(setBinding.getDependencies().toString(), 2, setBinding.getDependencies().size());
+    Set<Dependency<?>> expected = Sets.newHashSet();
+    for (Dependency<?> dep : setBinding.getDependencies()) {
+      Key key = dep.getKey();
+      Dependency<?> providerDependency =
+          Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType())));
+      expected.add(providerDependency);
+    }
+    assertEquals(expected, providerBinding.getDependencies());
+  }
+
+  private <T> Collection<T> collectValues(
+      Collection<? extends javax.inject.Provider<T>> providers) {
+    Collection<T> values = Lists.newArrayList();
+    for (javax.inject.Provider<T> provider : providers) {
+      values.add(provider.get());
+    }
+    return values;
+  }
+}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java
new file mode 100644
index 0000000..f3c9f63
--- /dev/null
+++ b/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java
@@ -0,0 +1,1241 @@
+/**
+ * Copyright (C) 2014 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.inject.multibindings;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.multibindings.SpiUtils.assertOptionalVisitor;
+import static com.google.inject.multibindings.SpiUtils.instance;
+import static com.google.inject.multibindings.SpiUtils.linked;
+import static com.google.inject.multibindings.SpiUtils.providerInstance;
+import static com.google.inject.multibindings.SpiUtils.providerKey;
+import static com.google.inject.name.Names.named;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Asserts;
+import com.google.inject.Binding;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.WeakKeySetUtils;
+import com.google.inject.multibindings.OptionalBinder.Actual;
+import com.google.inject.multibindings.OptionalBinder.Default;
+import com.google.inject.multibindings.SpiUtils.VisitType;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Elements;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.util.Modules;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class OptionalBinderTest extends TestCase {
+
+  private static final boolean HAS_JAVA_OPTIONAL;
+  private static final Class<?> JAVA_OPTIONAL_CLASS;
+  private static final Method JAVA_OPTIONAL_OR_ELSE;
+  static {
+    Class<?> optional = null;
+    Method orElse = null;
+    try {
+      optional = Class.forName("java.util.Optional");
+      orElse = optional.getDeclaredMethod("orElse", Object.class);
+    } catch (ClassNotFoundException ignored) {
+    } catch (NoSuchMethodException ignored) {
+    } catch (SecurityException ignored) {
+    }
+    HAS_JAVA_OPTIONAL = optional != null;
+    JAVA_OPTIONAL_CLASS = optional;
+    JAVA_OPTIONAL_OR_ELSE = orElse;
+  }
+
+  final Key<String> stringKey = Key.get(String.class);
+  final TypeLiteral<Optional<String>> optionalOfString = new TypeLiteral<Optional<String>>() {};
+  final TypeLiteral<?> javaOptionalOfString =  HAS_JAVA_OPTIONAL ?
+      OptionalBinder.javaOptionalOf(stringKey.getTypeLiteral()) : null;
+  final TypeLiteral<Optional<Provider<String>>> optionalOfProviderString =
+      new TypeLiteral<Optional<Provider<String>>>() {};
+  final TypeLiteral<?> javaOptionalOfProviderString = HAS_JAVA_OPTIONAL ?
+      OptionalBinder.javaOptionalOfProvider(stringKey.getTypeLiteral()) : null;
+  final TypeLiteral<Optional<javax.inject.Provider<String>>> optionalOfJavaxProviderString =
+      new TypeLiteral<Optional<javax.inject.Provider<String>>>() {};
+  final TypeLiteral<?> javaOptionalOfJavaxProviderString = HAS_JAVA_OPTIONAL ?
+      OptionalBinder.javaOptionalOfJavaxProvider(stringKey.getTypeLiteral()) : null;
+
+  final Key<Integer> intKey = Key.get(Integer.class);
+  final TypeLiteral<Optional<Integer>> optionalOfInteger = new TypeLiteral<Optional<Integer>>() {};
+  final TypeLiteral<?> javaOptionalOfInteger =  HAS_JAVA_OPTIONAL ?
+      OptionalBinder.javaOptionalOf(intKey.getTypeLiteral()) : null;
+  final TypeLiteral<Optional<Provider<Integer>>> optionalOfProviderInteger =
+      new TypeLiteral<Optional<Provider<Integer>>>() {};
+  final TypeLiteral<?> javaOptionalOfProviderInteger = HAS_JAVA_OPTIONAL ?
+      OptionalBinder.javaOptionalOfProvider(intKey.getTypeLiteral()) : null;
+  final TypeLiteral<Optional<javax.inject.Provider<Integer>>> optionalOfJavaxProviderInteger =
+      new TypeLiteral<Optional<javax.inject.Provider<Integer>>>() {};
+  final TypeLiteral<?> javaOptionalOfJavaxProviderInteger = HAS_JAVA_OPTIONAL ?
+      OptionalBinder.javaOptionalOfJavaxProvider(intKey.getTypeLiteral()) : null;
+
+  final TypeLiteral<List<String>> listOfStrings = new TypeLiteral<List<String>>() {};
+
+  public void testTypeNotBoundByDefault() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class);
+        requireBinding(new Key<Optional<String>>() {}); // the above specifies this.
+        requireBinding(String.class); // but it doesn't specify this.
+        binder().requireExplicitBindings(); // need to do this, otherwise String will JIT
+
+        if (HAS_JAVA_OPTIONAL) {
+          requireBinding(Key.get(javaOptionalOfString));
+        }
+      }
+    };
+
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException ce) {
+      assertContains(ce.getMessage(),
+          "1) Explicit bindings are required and java.lang.String is not explicitly bound.");
+      assertEquals(1, ce.getErrorMessages().size());
+    }
+  } 
+  
+  public void testOptionalIsAbsentByDefault() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class);
+      }
+    };
+
+    Injector injector = Guice.createInjector(module);
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertFalse(optional.isPresent());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertFalse(optionalP.isPresent());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertFalse(optionalJxP.isPresent());
+    
+    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, null, null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertFalse(optional.isPresent());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertFalse(optionalP.isPresent());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertFalse(optionalJxP.isPresent());
+    }
+  }
+  
+  public void testUsesUserBoundValue() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class);
+      }
+      @Provides String provideString() { return "foo"; }
+    };
+
+    Injector injector = Guice.createInjector(module);
+    assertEquals("foo", injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertEquals("foo", optional.get());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertEquals("foo", optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertEquals("foo", optionalJxP.get().get());
+    
+    assertOptionalVisitor(stringKey,
+        setOf(module),
+        VisitType.BOTH,
+        0,
+        null,
+        null,
+        providerInstance("foo"));
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertEquals("foo", optional.get());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertEquals("foo", optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertEquals("foo", optionalJxP.get().get());
+    }
+  }
+  
+  public void testSetDefault() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertEquals("a", injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertTrue(optional.isPresent());
+    assertEquals("a", optional.get());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertEquals("a", optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertEquals("a", optionalJxP.get().get());
+
+    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertTrue(optional.isPresent());
+      assertEquals("a", optional.get());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertEquals("a", optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertEquals("a", optionalJxP.get().get());
+    }
+  }
+  
+  public void testSetBinding() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertEquals("a", injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertTrue(optional.isPresent());
+    assertEquals("a", optional.get());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertEquals("a", optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertEquals("a", optionalJxP.get().get());
+    
+    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertTrue(optional.isPresent());
+      assertEquals("a", optional.get());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertEquals("a", optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertEquals("a", optionalJxP.get().get());
+    }
+  }
+  
+  public void testSetBindingOverridesDefault() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> optionalBinder =
+            OptionalBinder.newOptionalBinder(binder(), String.class);
+        optionalBinder.setDefault().toInstance("a");
+        optionalBinder.setBinding().toInstance("b");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertEquals("b", injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertTrue(optional.isPresent());
+    assertEquals("b", optional.get());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertEquals("b", optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertEquals("b", optionalJxP.get().get());
+    
+    assertOptionalVisitor(stringKey,
+        setOf(module),
+        VisitType.BOTH,
+        0,
+        instance("a"),
+        instance("b"),
+        null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertTrue(optional.isPresent());
+      assertEquals("b", optional.get());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertEquals("b", optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertEquals("b", optionalJxP.get().get());
+    }
+  }
+  
+  public void testSpreadAcrossModules() throws Exception {
+    Module module1 = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class);
+      }
+    };
+    Module module2 = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
+      }
+    };
+    Module module3 = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b");
+      }
+    };
+
+    Injector injector = Guice.createInjector(module1, module2, module3);
+    assertEquals("b", injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertTrue(optional.isPresent());
+    assertEquals("b", optional.get());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertEquals("b", optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertEquals("b", optionalJxP.get().get());
+    
+    assertOptionalVisitor(stringKey,
+        setOf(module1, module2, module3),
+        VisitType.BOTH,
+        0,
+        instance("a"),
+        instance("b"),
+        null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertTrue(optional.isPresent());
+      assertEquals("b", optional.get());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertEquals("b", optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertEquals("b", optionalJxP.get().get());
+    }
+  }
+  
+  public void testExactSameBindingCollapses_defaults() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault()
+            .toInstance(new String("a")); // using new String to ensure .equals is checked.
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault()
+            .toInstance(new String("a"));
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertEquals("a", injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertTrue(optional.isPresent());
+    assertEquals("a", optional.get());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertEquals("a", optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertEquals("a", optionalJxP.get().get());
+
+    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertTrue(optional.isPresent());
+      assertEquals("a", optional.get());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertEquals("a", optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertEquals("a", optionalJxP.get().get());
+    }
+  }
+  
+  public void testExactSameBindingCollapses_actual() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setBinding()
+            .toInstance(new String("a")); // using new String to ensure .equals is checked.
+        OptionalBinder.newOptionalBinder(binder(), String.class).setBinding()
+            .toInstance(new String("a"));
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertEquals("a", injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertTrue(optional.isPresent());
+    assertEquals("a", optional.get());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertEquals("a", optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertEquals("a", optionalJxP.get().get());
+
+    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertTrue(optional.isPresent());
+      assertEquals("a", optional.get());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertEquals("a", optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertEquals("a", optionalJxP.get().get());
+    }
+  }
+  
+  public void testDifferentBindingsFail_defaults() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b");
+      }
+    };
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size());
+      assertContains(ce.getMessage(),
+          "1) A binding to java.lang.String annotated with @" 
+              + Default.class.getName() + " was already configured at "
+              + module.getClass().getName() + ".configure(",
+          "at " + module.getClass().getName() + ".configure(");
+    }
+  }  
+  
+  public void testDifferentBindingsFail_actual() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a");
+        OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b");
+      }
+    };
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size());
+      assertContains(ce.getMessage(),
+          "1) A binding to java.lang.String annotated with @" 
+              + Actual.class.getName() + " was already configured at "
+              + module.getClass().getName() + ".configure(",
+          "at " + module.getClass().getName() + ".configure(");
+    }
+  }  
+  
+  public void testDifferentBindingsFail_both() {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b");
+        OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b");
+        OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("c");
+      }
+    };
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(ce.getMessage(), 2, ce.getErrorMessages().size());      
+      assertContains(ce.getMessage(),
+          "1) A binding to java.lang.String annotated with @"
+              + Default.class.getName() + " was already configured at "
+              + module.getClass().getName() + ".configure(",
+          "at " + module.getClass().getName() + ".configure(",
+          "2) A binding to java.lang.String annotated with @"
+              + Actual.class.getName() + " was already configured at "
+              + module.getClass().getName() + ".configure(",
+          "at " + module.getClass().getName() + ".configure(");
+    }
+  }
+  
+  public void testQualifiedAggregatesTogether() throws Exception {
+    Module module1 = new AbstractModule() {
+      @Override
+      protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo")));
+      }
+    };
+    Module module2 = new AbstractModule() {
+      @Override
+      protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo")))
+            .setDefault().toInstance("a");
+      }
+    };
+    Module module3 = new AbstractModule() {
+      @Override
+      protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo")))
+            .setBinding().toInstance("b");
+      }
+    };
+
+    Injector injector = Guice.createInjector(module1, module2, module3);
+    assertEquals("b", injector.getInstance(Key.get(String.class, Names.named("foo"))));
+
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString, Names.named("foo")));
+    assertTrue(optional.isPresent());
+    assertEquals("b", optional.get());
+
+    Optional<Provider<String>> optionalP =
+        injector.getInstance(Key.get(optionalOfProviderString, Names.named("foo")));
+    assertTrue(optionalP.isPresent());
+    assertEquals("b", optionalP.get().get());
+
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString, Names.named("foo")));
+    assertTrue(optionalJxP.isPresent());
+    assertEquals("b", optionalJxP.get().get());
+    
+    assertOptionalVisitor(Key.get(String.class, Names.named("foo")),
+        setOf(module1, module2, module3),
+        VisitType.BOTH,
+        0,
+        instance("a"),
+        instance("b"),
+        null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString, Names.named("foo"))));
+      assertTrue(optional.isPresent());
+      assertEquals("b", optional.get());
+
+      optionalP = toOptional(injector.getInstance
+          (Key.get(javaOptionalOfProviderString, Names.named("foo"))));
+      assertTrue(optionalP.isPresent());
+      assertEquals("b", optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(
+          Key.get(javaOptionalOfJavaxProviderString, Names.named("foo"))));
+      assertTrue(optionalJxP.isPresent());
+      assertEquals("b", optionalJxP.get().get());
+    }
+  }
+  
+  public void testMultipleDifferentOptionals() {
+    final Key<String> bKey = Key.get(String.class, named("b"));
+    final Key<String> cKey = Key.get(String.class, named("c"));
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
+        OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(1);
+        
+        OptionalBinder.newOptionalBinder(binder(), bKey).setDefault().toInstance("b");
+        OptionalBinder.newOptionalBinder(binder(), cKey).setDefault().toInstance("c");
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertEquals("a", injector.getInstance(String.class));
+    assertEquals(1, injector.getInstance(Integer.class).intValue());
+    assertEquals("b", injector.getInstance(bKey));
+    assertEquals("c", injector.getInstance(cKey));
+    
+    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 3, instance("a"), null, null);
+    assertOptionalVisitor(intKey, setOf(module), VisitType.BOTH, 3, instance(1), null, null);
+    assertOptionalVisitor(bKey, setOf(module), VisitType.BOTH, 3, instance("b"), null, null);
+    assertOptionalVisitor(cKey, setOf(module), VisitType.BOTH, 3, instance("c"), null, null);
+  }
+  
+  public void testOptionalIsAppropriatelyLazy() throws Exception {
+    Module module = new AbstractModule() {
+      int nextValue = 1;
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), Integer.class)
+            .setDefault().to(Key.get(Integer.class, Names.named("foo")));
+      }
+      @Provides @Named("foo") int provideInt() {
+        return nextValue++;
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+
+    Optional<Provider<Integer>> optionalP =
+        injector.getInstance(Key.get(optionalOfProviderInteger));
+    Optional<javax.inject.Provider<Integer>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderInteger));
+    
+    assertEquals(1, injector.getInstance(Integer.class).intValue());
+    assertEquals(2, injector.getInstance(Integer.class).intValue());
+    
+    // Calling .get() on an Optional<Integer> multiple times will keep giving the same thing
+    Optional<Integer> optional = injector.getInstance(Key.get(optionalOfInteger));
+    assertEquals(3, optional.get().intValue());
+    assertEquals(3, optional.get().intValue());
+    // But getting another Optional<Integer> will give a new one.
+    assertEquals(4, injector.getInstance(Key.get(optionalOfInteger)).get().intValue());
+    
+    // And the Optional<Provider> will return a provider that gives a new value each time.
+    assertEquals(5, optionalP.get().get().intValue());
+    assertEquals(6, optionalP.get().get().intValue());
+    
+    assertEquals(7, optionalJxP.get().get().intValue());
+    assertEquals(8, optionalJxP.get().get().intValue());
+
+    // and same rules with java.util.Optional
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger)));
+      assertEquals(9, optional.get().intValue());
+      assertEquals(9, optional.get().intValue());
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger)));
+      assertEquals(10, optional.get().intValue());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderInteger)));
+      assertEquals(11, optionalP.get().get().intValue());
+      assertEquals(12, optionalP.get().get().intValue());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderInteger)));
+      assertEquals(13, optionalJxP.get().get().intValue());
+      assertEquals(14, optionalJxP.get().get().intValue());
+    }
+  }
+  
+  public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_default()
+      throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class)
+            .setDefault().toProvider(Providers.<String>of(null));
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertNull(injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertFalse(optional.isPresent());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertNull(optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertNull(optionalJxP.get().get());
+    
+    assertOptionalVisitor(stringKey,
+        setOf(module),
+        VisitType.BOTH,
+        0,
+        SpiUtils.<String>providerInstance(null),
+        null,
+        null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertFalse(optional.isPresent());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertNull(optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertNull(optionalJxP.get().get());
+    }
+  }
+  
+  public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_actual()
+      throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class)
+            .setBinding().toProvider(Providers.<String>of(null));
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertNull(injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertFalse(optional.isPresent());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertNull(optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertNull(optionalJxP.get().get());
+    
+    assertOptionalVisitor(stringKey,
+        setOf(module),
+        VisitType.BOTH,
+        0,
+        null,
+        SpiUtils.<String>providerInstance(null),
+        null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertFalse(optional.isPresent());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertNull(optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertNull(optionalJxP.get().get());
+    }
+  }
+  
+  // TODO(sameb): Maybe change this?
+  public void testLinkedToNullActualDoesntFallbackToDefault() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
+        OptionalBinder.newOptionalBinder(binder(), String.class)
+            .setBinding().toProvider(Providers.<String>of(null));
+      }
+    };
+    Injector injector = Guice.createInjector(module);
+    assertNull(injector.getInstance(String.class));
+    
+    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
+    assertFalse(optional.isPresent());
+    
+    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
+    assertTrue(optionalP.isPresent());
+    assertNull(optionalP.get().get());
+    
+    Optional<javax.inject.Provider<String>> optionalJxP =
+        injector.getInstance(Key.get(optionalOfJavaxProviderString));
+    assertTrue(optionalJxP.isPresent());
+    assertNull(optionalP.get().get());
+    
+    assertOptionalVisitor(stringKey,
+        setOf(module),
+        VisitType.BOTH,
+        0,
+        instance("a"),
+        SpiUtils.<String>providerInstance(null),
+        null);
+
+    if (HAS_JAVA_OPTIONAL) {
+      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
+      assertFalse(optional.isPresent());
+
+      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
+      assertTrue(optionalP.isPresent());
+      assertNull(optionalP.get().get());
+
+      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
+      assertTrue(optionalJxP.isPresent());
+      assertNull(optionalJxP.get().get());
+    }
+  }
+
+  public void testSourceLinesInException() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          OptionalBinder.newOptionalBinder(binder(),  Integer.class).setDefault();
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(), "No implementation for java.lang.Integer",
+          "at " + getClass().getName());
+    }
+  }
+
+  public void testDependencies_both() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> optionalbinder =
+            OptionalBinder.newOptionalBinder(binder(), String.class);
+        optionalbinder.setDefault().toInstance("A");
+        optionalbinder.setBinding().to(Key.get(String.class, Names.named("b")));
+        bindConstant().annotatedWith(Names.named("b")).to("B");
+      }
+    });
+
+    Binding<String> binding = injector.getBinding(Key.get(String.class));
+    HasDependencies withDependencies = (HasDependencies) binding;
+    Set<String> elements = Sets.newHashSet();
+    elements.addAll(recurseForDependencies(injector, withDependencies));
+    assertEquals(ImmutableSet.of("B"), elements);
+  }
+
+  public void testDependencies_actual() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> optionalbinder =
+            OptionalBinder.newOptionalBinder(binder(), String.class);
+        optionalbinder.setBinding().to(Key.get(String.class, Names.named("b")));
+        bindConstant().annotatedWith(Names.named("b")).to("B");
+      }
+    });
+
+    Binding<String> binding = injector.getBinding(Key.get(String.class));
+    HasDependencies withDependencies = (HasDependencies) binding;
+    Set<String> elements = Sets.newHashSet();
+    elements.addAll(recurseForDependencies(injector, withDependencies));
+    assertEquals(ImmutableSet.of("B"), elements);
+  }
+
+  public void testDependencies_default() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> optionalbinder =
+            OptionalBinder.newOptionalBinder(binder(), String.class);
+        optionalbinder.setDefault().toInstance("A");
+      }
+    });
+
+    Binding<String> binding = injector.getBinding(Key.get(String.class));
+    HasDependencies withDependencies = (HasDependencies) binding;
+    Set<String> elements = Sets.newHashSet();
+    elements.addAll(recurseForDependencies(injector, withDependencies));
+    assertEquals(ImmutableSet.of("A"), elements);
+  }
+  
+  @SuppressWarnings("rawtypes")
+  private Set<String> recurseForDependencies(Injector injector, HasDependencies hasDependencies) {
+    Set<String> elements = Sets.newHashSet();
+    for (Dependency<?> dependency : hasDependencies.getDependencies()) {
+      Binding<?> binding = injector.getBinding(dependency.getKey());
+      HasDependencies deps = (HasDependencies) binding;
+      if (binding instanceof InstanceBinding) {
+        elements.add((String) ((InstanceBinding) binding).getInstance());
+      } else {
+        elements.addAll(recurseForDependencies(injector, deps));
+      }
+    }    
+    return elements;
+  }
+
+  /**
+   * Doubly-installed modules should not conflict, even when one is overridden.
+   */
+  public void testModuleOverrideRepeatedInstalls_toInstance() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class);
+        b.setDefault().toInstance("A");
+        b.setBinding().toInstance("B");
+      }
+    };
+
+    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class)));
+
+    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
+    assertEquals("B", injector.getInstance(Key.get(String.class)));
+
+    assertOptionalVisitor(stringKey,
+        setOf(m, Modules.override(m).with(m)),
+        VisitType.BOTH,
+        0,
+        instance("A"),
+        instance("B"),
+        null);
+  }
+
+  public void testModuleOverrideRepeatedInstalls_toKey() {
+    final Key<String> aKey = Key.get(String.class, Names.named("A_string"));
+    final Key<String> bKey = Key.get(String.class, Names.named("B_string"));
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        bind(aKey).toInstance("A");
+        bind(bKey).toInstance("B");
+
+        OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class);
+        b.setDefault().to(aKey);
+        b.setBinding().to(bKey);
+      }
+    };
+
+    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class)));
+
+    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
+    assertEquals("B", injector.getInstance(Key.get(String.class)));
+
+    assertOptionalVisitor(stringKey,
+        setOf(m, Modules.override(m).with(m)),
+        VisitType.BOTH,
+        0,
+        linked(aKey),
+        linked(bKey),
+        null);
+  }
+
+  public void testModuleOverrideRepeatedInstalls_toProviderInstance() {
+    // Providers#of() does not redefine equals/hashCode, so use the same one both times.
+    final Provider<String> aProvider = Providers.of("A");
+    final Provider<String> bProvider = Providers.of("B");
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class);
+        b.setDefault().toProvider(aProvider);
+        b.setBinding().toProvider(bProvider);
+      }
+    };
+
+    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class)));
+
+    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
+    assertEquals("B", injector.getInstance(Key.get(String.class)));
+
+    assertOptionalVisitor(stringKey,
+        setOf(m, Modules.override(m).with(m)),
+        VisitType.BOTH,
+        0,
+        providerInstance("A"),
+        providerInstance("B"),
+        null);
+  }
+
+  private static class AStringProvider implements Provider<String> {
+    public String get() {
+      return "A";
+    }
+  }
+
+  private static class BStringProvider implements Provider<String> {
+    public String get() {
+      return "B";
+    }
+  }
+
+  public void testModuleOverrideRepeatedInstalls_toProviderKey() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class);
+        b.setDefault().toProvider(Key.get(AStringProvider.class));
+        b.setBinding().toProvider(Key.get(BStringProvider.class));
+      }
+    };
+
+    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class)));
+
+    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
+    assertEquals("B", injector.getInstance(Key.get(String.class)));
+
+    assertOptionalVisitor(stringKey,
+        setOf(m, Modules.override(m).with(m)),
+        VisitType.BOTH,
+        0,
+        providerKey(Key.get(AStringProvider.class)),
+        providerKey(Key.get(BStringProvider.class)),
+        null);
+  }
+
+  private static class StringGrabber {
+    private final String string;
+
+    @SuppressWarnings("unused")  // Found by reflection
+    public StringGrabber(@Named("A_string") String string) {
+      this.string = string;
+    }
+
+    @SuppressWarnings("unused")  // Found by reflection
+    public StringGrabber(@Named("B_string") String string, int unused) {
+      this.string = string;
+    }
+
+    @Override
+    public int hashCode() {
+      return string.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string);
+    }
+
+    @Override
+    public String toString() {
+      return "StringGrabber(" + string + ")";
+    }
+  }
+
+  public void testModuleOverrideRepeatedInstalls_toConstructor() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        Key<String> aKey = Key.get(String.class, Names.named("A_string"));
+        Key<String> bKey = Key.get(String.class, Names.named("B_string"));
+        bind(aKey).toInstance("A");
+        bind(bKey).toInstance("B");
+        bind(Integer.class).toInstance(0);  // used to disambiguate constructors
+
+
+        OptionalBinder<StringGrabber> b =
+            OptionalBinder.newOptionalBinder(binder(), StringGrabber.class);
+        try {
+          b.setDefault().toConstructor(
+              StringGrabber.class.getConstructor(String.class));
+          b.setBinding().toConstructor(
+              StringGrabber.class.getConstructor(String.class, int.class));
+        } catch (NoSuchMethodException e) {
+          fail("No such method: " + e.getMessage());
+        }
+      }
+    };
+
+    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(StringGrabber.class)).string);
+
+    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
+    assertEquals("B", injector.getInstance(Key.get(StringGrabber.class)).string);
+  }
+
+  /**
+   * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or
+   * explicitly bound in {@link Scopes#NO_SCOPE}.
+   */
+  public void testDuplicateUnscopedBindings() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<Integer> b = OptionalBinder.newOptionalBinder(binder(), Integer.class);
+        b.setDefault().to(Key.get(Integer.class, named("foo")));
+        b.setDefault().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE);
+        b.setBinding().to(Key.get(Integer.class, named("foo")));
+        b.setBinding().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE);
+      }
+      @Provides @Named("foo") int provideInt() { return 5; }
+    };
+    assertEquals(5, Guice.createInjector(m).getInstance(Integer.class).intValue());
+  }
+
+  /**
+   * Ensure key hash codes are fixed at injection time, not binding time.
+   */
+  public void testKeyHashCodesFixedAtInjectionTime() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<List<String>> b = OptionalBinder.newOptionalBinder(binder(), listOfStrings);
+        List<String> list = Lists.newArrayList();
+        b.setDefault().toInstance(list);
+        b.setBinding().toInstance(list);
+        list.add("A");
+        list.add("B");
+      }
+    };
+
+    Injector injector = Guice.createInjector(m);
+    for (Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
+      Key<?> bindingKey = entry.getKey();
+      Key<?> clonedKey;
+      if (bindingKey.getAnnotation() != null) {
+        clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation());
+      } else if (bindingKey.getAnnotationType() != null) {
+        clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType());
+      } else {
+        clonedKey = Key.get(bindingKey.getTypeLiteral());
+      }
+      assertEquals(bindingKey, clonedKey);
+      assertEquals("Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(),
+          bindingKey.hashCode(), clonedKey.hashCode());
+    }
+  }
+
+  /**
+   * Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}.
+   */
+  public void testBindingKeysFixedOnReturnFromGetElements() {
+    final List<String> list = Lists.newArrayList();
+    Module m = new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<List<String>> b = OptionalBinder.newOptionalBinder(binder(), listOfStrings);
+        b.setDefault().toInstance(list);
+        list.add("A");
+        list.add("B");
+      }
+    };
+
+    InstanceBinding<?> binding = Iterables.getOnlyElement(
+        Iterables.filter(Elements.getElements(m), InstanceBinding.class));
+    Key<?> keyBefore = binding.getKey();
+    assertEquals(listOfStrings, keyBefore.getTypeLiteral());
+
+    list.add("C");
+    Key<?> keyAfter = binding.getKey();
+    assertSame(keyBefore, keyAfter);
+  }
+
+  @BindingAnnotation
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
+  private static @interface Marker {}
+
+  @Marker
+  public void testMatchingMarkerAnnotations() throws Exception {
+    Method m = OptionalBinderTest.class.getDeclaredMethod("testMatchingMarkerAnnotations");
+    assertNotNull(m);
+    final Annotation marker = m.getAnnotation(Marker.class);
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override public void configure() {
+        OptionalBinder<Integer> mb1 =
+            OptionalBinder.newOptionalBinder(binder(), Key.get(Integer.class, Marker.class));
+        OptionalBinder<Integer> mb2 =
+            OptionalBinder.newOptionalBinder(binder(), Key.get(Integer.class, marker));
+        mb1.setDefault().toInstance(1);
+        mb2.setBinding().toInstance(2);
+
+        // This assures us that the two binders are equivalent, so we expect the instance added to
+        // each to have been added to one set.
+        assertEquals(mb1, mb2);
+      }
+    });
+    Integer i1 = injector.getInstance(Key.get(Integer.class, Marker.class));
+    Integer i2 = injector.getInstance(Key.get(Integer.class, marker));
+
+    // These must be identical, because the marker annotations collapsed to the same thing.
+    assertSame(i1, i2);
+    assertEquals(2, i2.intValue());
+  }
+  
+ // Tests for com.google.inject.internal.WeakKeySet not leaking memory.
+ public void testWeakKeySet_integration() {   
+   Injector parentInjector = Guice.createInjector(new AbstractModule() {
+         @Override protected void configure() {
+           bind(String.class).toInstance("hi");
+         }
+       });
+   WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class));
+
+   Injector childInjector = parentInjector.createChildInjector(new AbstractModule() {
+     @Override protected void configure() {
+       OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(4);
+     }
+   });
+   WeakReference<Injector> weakRef = new WeakReference<Injector>(childInjector);
+   WeakKeySetUtils.assertBlacklisted(parentInjector, Key.get(Integer.class));
+   
+   // Clear the ref, GC, and ensure that we are no longer blacklisting.
+   childInjector = null;
+   
+   Asserts.awaitClear(weakRef);
+   WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class));
+ }
+
+ public void testCompareEqualsAgainstOtherAnnotation() {
+   OptionalBinder.Actual impl1 = new OptionalBinder.ActualImpl("foo");
+   OptionalBinder.Actual other1 = Dummy.class.getAnnotation(OptionalBinder.Actual.class);
+   assertEquals(impl1, other1);
+
+   OptionalBinder.Default impl2 = new OptionalBinder.DefaultImpl("foo");
+   OptionalBinder.Default other2 = Dummy.class.getAnnotation(OptionalBinder.Default.class);
+   assertEquals(impl2, other2);
+
+   assertFalse(impl1.equals(impl2));
+   assertFalse(impl1.equals(other2));
+   assertFalse(impl2.equals(other1));
+   assertFalse(other1.equals(other2));
+ }
+
+  @OptionalBinder.Actual("foo")
+  @OptionalBinder.Default("foo")
+  static class Dummy {}
+  
+  @SuppressWarnings("unchecked") 
+  private <V> Set<V> setOf(V... elements) {
+    return ImmutableSet.copyOf(elements);
+  }
+
+  @SuppressWarnings("unchecked")
+  private <T> Optional<T> toOptional(Object object) throws Exception {
+    assertTrue("not a java.util.Optional: " + object.getClass(),
+        JAVA_OPTIONAL_CLASS.isInstance(object));
+    return Optional.fromNullable((T) JAVA_OPTIONAL_OR_ELSE.invoke(object, (Void) null));
+  }
+}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/ProvidesIntoTest.java b/extensions/multibindings/test/com/google/inject/multibindings/ProvidesIntoTest.java
new file mode 100644
index 0000000..62c7a58
--- /dev/null
+++ b/extensions/multibindings/test/com/google/inject/multibindings/ProvidesIntoTest.java
@@ -0,0 +1,373 @@
+/**
+ * Copyright (C) 2015 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.inject.multibindings;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.name.Names.named;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.multibindings.ProvidesIntoOptional.Type;
+import com.google.inject.name.Named;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests the various @ProvidesInto annotations.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class ProvidesIntoTest extends TestCase {
+
+  public void testAnnotation() throws Exception {
+    Injector injector = Guice.createInjector(MultibindingsScanner.asModule(), new AbstractModule() {
+      @Override protected void configure() {}
+
+      @ProvidesIntoSet
+      @Named("foo")
+      String setFoo() { return "foo"; }
+
+      @ProvidesIntoSet
+      @Named("foo")
+      String setFoo2() { return "foo2"; }
+
+      @ProvidesIntoSet
+      @Named("bar")
+      String setBar() { return "bar"; }
+
+      @ProvidesIntoSet
+      @Named("bar")
+      String setBar2() { return "bar2"; }
+
+      @ProvidesIntoSet
+      String setNoAnnotation() { return "na"; }
+
+      @ProvidesIntoSet
+      String setNoAnnotation2() { return "na2"; }
+
+      @ProvidesIntoMap
+      @StringMapKey("fooKey")
+      @Named("foo")
+      String mapFoo() { return "foo"; }
+
+      @ProvidesIntoMap
+      @StringMapKey("foo2Key")
+      @Named("foo")
+      String mapFoo2() { return "foo2"; }
+
+      @ProvidesIntoMap
+      @ClassMapKey(String.class)
+      @Named("bar")
+      String mapBar() { return "bar"; }
+
+      @ProvidesIntoMap
+      @ClassMapKey(Number.class)
+      @Named("bar")
+      String mapBar2() { return "bar2"; }
+
+      @ProvidesIntoMap
+      @TestEnumKey(TestEnum.A)
+      String mapNoAnnotation() { return "na"; }
+
+      @ProvidesIntoMap
+      @TestEnumKey(TestEnum.B)
+      String mapNoAnnotation2() { return "na2"; }
+
+      @ProvidesIntoMap
+      @WrappedKey(number = 1)
+      Number wrapped1() { return 11; }
+
+      @ProvidesIntoMap
+      @WrappedKey(number = 2)
+      Number wrapped2() { return 22; }
+
+      @ProvidesIntoOptional(ProvidesIntoOptional.Type.DEFAULT)
+      @Named("foo")
+      String optionalDefaultFoo() { return "foo"; }
+
+      @ProvidesIntoOptional(ProvidesIntoOptional.Type.ACTUAL)
+      @Named("foo")
+      String optionalActualFoo() { return "foo2"; }
+
+      @ProvidesIntoOptional(ProvidesIntoOptional.Type.DEFAULT)
+      @Named("bar")
+      String optionalDefaultBar() { return "bar"; }
+
+      @ProvidesIntoOptional(ProvidesIntoOptional.Type.ACTUAL)
+      String optionalActualBar() { return "na2"; }
+    });
+
+    Set<String> fooSet = injector.getInstance(new Key<Set<String>>(named("foo")) {});
+    assertEquals(ImmutableSet.of("foo", "foo2"), fooSet);
+
+    Set<String> barSet = injector.getInstance(new Key<Set<String>>(named("bar")) {});
+    assertEquals(ImmutableSet.of("bar", "bar2"), barSet);
+
+    Set<String> noAnnotationSet = injector.getInstance(new Key<Set<String>>() {});
+    assertEquals(ImmutableSet.of("na", "na2"), noAnnotationSet);
+
+    Map<String, String> fooMap =
+        injector.getInstance(new Key<Map<String, String>>(named("foo")) {});
+    assertEquals(ImmutableMap.of("fooKey", "foo", "foo2Key", "foo2"), fooMap);
+
+    Map<Class<?>, String> barMap =
+        injector.getInstance(new Key<Map<Class<?>, String>>(named("bar")) {});
+    assertEquals(ImmutableMap.of(String.class, "bar", Number.class, "bar2"), barMap);
+
+    Map<TestEnum, String> noAnnotationMap =
+        injector.getInstance(new Key<Map<TestEnum, String>>() {});
+    assertEquals(ImmutableMap.of(TestEnum.A, "na", TestEnum.B, "na2"), noAnnotationMap);
+
+    Map<WrappedKey, Number> wrappedMap =
+        injector.getInstance(new Key<Map<WrappedKey, Number>>() {});
+    assertEquals(ImmutableMap.of(wrappedKeyFor(1), 11, wrappedKeyFor(2), 22), wrappedMap);
+
+    Optional<String> fooOptional =
+        injector.getInstance(new Key<Optional<String>>(named("foo")) {});
+    assertEquals("foo2", fooOptional.get());
+
+    Optional<String> barOptional =
+        injector.getInstance(new Key<Optional<String>>(named("bar")) {});
+    assertEquals("bar", barOptional.get());
+
+    Optional<String> noAnnotationOptional =
+        injector.getInstance(new Key<Optional<String>>() {});
+    assertEquals("na2", noAnnotationOptional.get());
+  }
+
+  enum TestEnum {
+    A, B
+  }
+
+  @MapKey(unwrapValue = true)
+  @Retention(RUNTIME)
+  @interface TestEnumKey {
+    TestEnum value();
+  }
+
+  @MapKey(unwrapValue = false)
+  @Retention(RUNTIME)
+  @interface WrappedKey {
+    int number();
+  }
+  
+  @SuppressWarnings("unused") @WrappedKey(number=1) private static Object wrappedKey1Holder;
+  @SuppressWarnings("unused") @WrappedKey(number=2) private static Object wrappedKey2Holder;
+  WrappedKey wrappedKeyFor(int number) throws Exception {
+    Field field;
+    switch (number) {
+      case 1:
+        field = ProvidesIntoTest.class.getDeclaredField("wrappedKey1Holder");
+        break;
+      case 2:
+        field = ProvidesIntoTest.class.getDeclaredField("wrappedKey2Holder");
+        break;
+      default:
+        throw new IllegalArgumentException("only 1 or 2 supported");
+    }
+    return field.getAnnotation(WrappedKey.class);
+  }
+  
+  public void testDoubleScannerIsIgnored() {
+    Injector injector = Guice.createInjector(
+        MultibindingsScanner.asModule(),
+        MultibindingsScanner.asModule(),
+        new AbstractModule() {
+          @Override protected void configure() {}
+          @ProvidesIntoSet String provideFoo() { return "foo"; }
+        }
+    );
+    assertEquals(ImmutableSet.of("foo"), injector.getInstance(new Key<Set<String>>() {}));
+  }
+  
+  @MapKey(unwrapValue = true)
+  @Retention(RUNTIME)
+  @interface ArrayUnwrappedKey {
+    int[] value();
+  }
+  
+  public void testArrayKeys_unwrapValuesTrue() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {}
+      @ProvidesIntoMap @ArrayUnwrappedKey({1, 2}) String provideFoo() { return "foo"; }
+    };
+    try {
+      Guice.createInjector(MultibindingsScanner.asModule(), m);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      assertContains(ce.getMessage(),
+          "Array types are not allowed in a MapKey with unwrapValue=true: "
+              + ArrayUnwrappedKey.class.getName(),
+          "at " + m.getClass().getName() + ".provideFoo(");
+    }    
+  }
+
+  @MapKey(unwrapValue = false)
+  @Retention(RUNTIME)
+  @interface ArrayWrappedKey {
+    int[] number();
+  }
+  
+  @SuppressWarnings("unused") @ArrayWrappedKey(number={1, 2}) private static Object arrayWrappedKeyHolder12;
+  @SuppressWarnings("unused") @ArrayWrappedKey(number={3, 4}) private static Object arrayWrappedKeyHolder34;
+  ArrayWrappedKey arrayWrappedKeyFor(int number) throws Exception {
+    Field field;
+    switch (number) {
+      case 12:
+        field = ProvidesIntoTest.class.getDeclaredField("arrayWrappedKeyHolder12");
+        break;
+      case 34:
+        field = ProvidesIntoTest.class.getDeclaredField("arrayWrappedKeyHolder34");
+        break;
+      default:
+        throw new IllegalArgumentException("only 1 or 2 supported");
+    }
+    return field.getAnnotation(ArrayWrappedKey.class);
+  }
+  
+  public void testArrayKeys_unwrapValuesFalse() throws Exception {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {}
+      @ProvidesIntoMap @ArrayWrappedKey(number = {1, 2}) String provideFoo() { return "foo"; }
+      @ProvidesIntoMap @ArrayWrappedKey(number = {3, 4}) String provideBar() { return "bar"; }
+    };
+    Injector injector = Guice.createInjector(MultibindingsScanner.asModule(), m);
+    Map<ArrayWrappedKey, String> map =
+        injector.getInstance(new Key<Map<ArrayWrappedKey, String>>() {});
+    ArrayWrappedKey key12 = arrayWrappedKeyFor(12);
+    ArrayWrappedKey key34 = arrayWrappedKeyFor(34);
+    assertEquals("foo", map.get(key12));
+    assertEquals("bar", map.get(key34));
+    assertEquals(2, map.size());
+  }
+  
+  public void testProvidesIntoSetWithMapKey() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {}
+      @ProvidesIntoSet @TestEnumKey(TestEnum.A) String provideFoo() { return "foo"; }
+    };
+    try {
+      Guice.createInjector(MultibindingsScanner.asModule(), m);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      assertContains(ce.getMessage(), "Found a MapKey annotation on non map binding at "
+          + m.getClass().getName() + ".provideFoo");
+    }
+  }
+  
+  public void testProvidesIntoOptionalWithMapKey() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {}
+
+      @ProvidesIntoOptional(Type.ACTUAL)
+      @TestEnumKey(TestEnum.A)
+      String provideFoo() {
+        return "foo";
+      }
+    };
+    try {
+      Guice.createInjector(MultibindingsScanner.asModule(), m);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      assertContains(ce.getMessage(), "Found a MapKey annotation on non map binding at "
+          + m.getClass().getName() + ".provideFoo");
+    }
+  }
+  
+  public void testProvidesIntoMapWithoutMapKey() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {}
+      @ProvidesIntoMap String provideFoo() { return "foo"; }
+    };
+    try {
+      Guice.createInjector(MultibindingsScanner.asModule(), m);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      assertContains(ce.getMessage(), "No MapKey found for map binding at "
+          + m.getClass().getName() + ".provideFoo");
+    }
+  }
+  
+  @MapKey(unwrapValue = true)
+  @Retention(RUNTIME)
+  @interface TestEnumKey2 {
+    TestEnum value();
+  }
+  
+  public void testMoreThanOneMapKeyAnnotation() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {}
+
+      @ProvidesIntoMap
+      @TestEnumKey(TestEnum.A)
+      @TestEnumKey2(TestEnum.B)
+      String provideFoo() {
+        return "foo";
+      }
+    };
+    try {
+      Guice.createInjector(MultibindingsScanner.asModule(), m);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      assertContains(ce.getMessage(), "Found more than one MapKey annotations on "
+          + m.getClass().getName() + ".provideFoo");
+    }    
+  }
+  
+  @MapKey(unwrapValue = true)
+  @Retention(RUNTIME)
+  @interface MissingValueMethod {
+  }
+  
+  public void testMapKeyMissingValueMethod() {
+    Module m = new AbstractModule() {
+      @Override protected void configure() {}
+
+      @ProvidesIntoMap
+      @MissingValueMethod
+      String provideFoo() {
+        return "foo";
+      }
+    };
+    try {
+      Guice.createInjector(MultibindingsScanner.asModule(), m);
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(1, ce.getErrorMessages().size());
+      assertContains(ce.getMessage(), "No 'value' method in MapKey with unwrapValue=true: "
+          + MissingValueMethod.class.getName());
+    }    
+  }
+}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/RealElementTest.java b/extensions/multibindings/test/com/google/inject/multibindings/RealElementTest.java
new file mode 100644
index 0000000..8dabf83
--- /dev/null
+++ b/extensions/multibindings/test/com/google/inject/multibindings/RealElementTest.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2014 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.inject.multibindings;
+
+import com.google.inject.multibindings.Element.Type;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link RealElement}.
+ */
+public class RealElementTest extends TestCase {
+  
+  private Element systemElement;
+  private RealElement realElement;
+  
+  @Override protected void setUp() throws Exception {
+    this.systemElement = Holder.class.getAnnotation(Element.class);
+    this.realElement = new RealElement("b", Type.MULTIBINDER, "a", 1);
+  }
+  
+  public void testEquals() {
+    assertEquals(systemElement, realElement);
+    assertEquals(realElement, systemElement);
+  }
+  
+  public void testHashCode() {
+    assertEquals(systemElement.hashCode(), realElement.hashCode());
+  }
+  
+  public void testProperties() {
+    assertEquals("a", realElement.keyType());
+    assertEquals("b", realElement.setName());
+    assertEquals(Type.MULTIBINDER, realElement.type());
+    assertEquals(1, realElement.uniqueId());
+  }
+  
+  
+  @Element(keyType = "a", setName = "b", type = Type.MULTIBINDER, uniqueId = 1)
+  static class Holder {}
+
+}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java b/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java
new file mode 100644
index 0000000..fd23f6b
--- /dev/null
+++ b/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java
@@ -0,0 +1,1117 @@
+/**
+ * Copyright (C) 2010 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.inject.multibindings;
+
+import static com.google.inject.multibindings.MapBinder.entryOfProviderOf;
+import static com.google.inject.multibindings.MapBinder.mapOf;
+import static com.google.inject.multibindings.MapBinder.mapOfJavaxProviderOf;
+import static com.google.inject.multibindings.MapBinder.mapOfProviderOf;
+import static com.google.inject.multibindings.MapBinder.mapOfSetOfProviderOf;
+import static com.google.inject.multibindings.Multibinder.collectionOfJavaxProvidersOf;
+import static com.google.inject.multibindings.Multibinder.collectionOfProvidersOf;
+import static com.google.inject.multibindings.Multibinder.setOf;
+import static com.google.inject.multibindings.OptionalBinder.javaOptionalOfJavaxProvider;
+import static com.google.inject.multibindings.OptionalBinder.javaOptionalOfProvider;
+import static com.google.inject.multibindings.OptionalBinder.optionalOfJavaxProvider;
+import static com.google.inject.multibindings.OptionalBinder.optionalOfProvider;
+import static com.google.inject.multibindings.SpiUtils.BindType.INSTANCE;
+import static com.google.inject.multibindings.SpiUtils.BindType.LINKED;
+import static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_INSTANCE;
+import static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_KEY;
+import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH;
+import static com.google.inject.multibindings.SpiUtils.VisitType.INJECTOR;
+import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.multibindings.Indexer.IndexedBinding;
+import com.google.inject.multibindings.MapBinder.RealMapBinder.ProviderMapEntry;
+import com.google.inject.multibindings.OptionalBinder.Source;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.LinkedKeyBinding;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderKeyBinding;
+import com.google.inject.spi.ProviderLookup;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utilities for testing the Multibinder & MapBinder extension SPI.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class SpiUtils {
+
+  private static final boolean HAS_JAVA_OPTIONAL;
+  static {
+    Class<?> optional = null;
+    try {
+      optional = Class.forName("java.util.Optional");
+    } catch (ClassNotFoundException ignored) {}
+    HAS_JAVA_OPTIONAL = optional != null;
+  }
+
+  /** The kind of test we should perform.  A live Injector, a raw Elements (Module) test, or both. */
+  enum VisitType { INJECTOR, MODULE, BOTH }
+  
+  /**
+   * Asserts that MapBinderBinding visitors for work correctly.
+   * 
+   * @param <T> The type of the binding
+   * @param mapKey The key the map belongs to.
+   * @param keyType the TypeLiteral of the key of the map
+   * @param valueType the TypeLiteral of the value of the map
+   * @param modules The modules that define the mapbindings
+   * @param visitType The kind of test we should perform.  A live Injector, a raw Elements (Module) test, or both.
+   * @param allowDuplicates If duplicates are allowed.
+   * @param expectedMapBindings The number of other mapbinders we expect to see.
+   * @param results The kind of bindings contained in the mapbinder.
+   */
+  static <T> void assertMapVisitor(Key<T> mapKey, TypeLiteral<?> keyType, TypeLiteral<?> valueType,
+      Iterable<? extends Module> modules, VisitType visitType, boolean allowDuplicates,
+      int expectedMapBindings, MapResult... results) {
+    if(visitType == null) {
+      fail("must test something");
+    }
+
+    if (visitType == BOTH || visitType == INJECTOR) {
+      mapInjectorTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings,
+          results);
+    }
+
+    if (visitType == BOTH || visitType == MODULE) {
+      mapModuleTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings,
+          results);
+    }
+  }
+  
+  @SuppressWarnings("unchecked")
+  private static <T> void mapInjectorTest(Key<T> mapKey, TypeLiteral<?> keyType,
+      TypeLiteral<?> valueType, Iterable<? extends Module> modules, boolean allowDuplicates,
+      int expectedMapBindings, MapResult... results) {
+    Injector injector = Guice.createInjector(modules);
+    Visitor<T> visitor = new Visitor<T>();
+    Binding<T> mapBinding = injector.getBinding(mapKey);
+    MapBinderBinding<T> mapbinder = (MapBinderBinding<T>)mapBinding.acceptTargetVisitor(visitor);
+    assertNotNull(mapbinder);
+    assertEquals(keyType, mapbinder.getKeyTypeLiteral());
+    assertEquals(valueType, mapbinder.getValueTypeLiteral());
+    assertEquals(allowDuplicates, mapbinder.permitsDuplicates());
+    List<Map.Entry<?, Binding<?>>> entries = Lists.newArrayList(mapbinder.getEntries());
+    List<MapResult> mapResults = Lists.newArrayList(results);
+    assertEquals("wrong entries, expected: " + mapResults + ", but was: " + entries,
+        mapResults.size(), entries.size());
+
+    for(MapResult result : mapResults) {
+      Map.Entry<?, Binding<?>> found = null;
+      for(Map.Entry<?, Binding<?>> entry : entries) {
+        Object key = entry.getKey();
+        Binding<?> value = entry.getValue();
+        if(key.equals(result.k) && matches(value, result.v)) {
+          found = entry;
+          break;
+        }
+      }
+      if(found == null) {
+        fail("Could not find entry: " + result + " in remaining entries: " + entries);
+      } else {
+        assertTrue("mapBinder doesn't contain: " + found.getValue(), 
+            mapbinder.containsElement(found.getValue()));
+        entries.remove(found);
+      }
+    }
+    
+    if(!entries.isEmpty()) {
+      fail("Found all entries of: " + mapResults + ", but more were left over: " + entries);
+    }
+    
+    Key<?> mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType));
+    Key<?> mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType));
+    Key<?> mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType));
+    Key<?> mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType)));
+    Key<?> setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType)));
+    Key<?> collectionOfProvidersOfEntryOfProvider =
+        mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType)));
+    Key<?> collectionOfJavaxProvidersOfEntryOfProvider =
+        mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType)));
+    boolean entrySetMatch = false;
+    boolean mapJavaxProviderMatch = false;
+    boolean mapProviderMatch = false;
+    boolean mapSetMatch = false; 
+    boolean mapSetProviderMatch = false;
+    boolean collectionOfProvidersOfEntryOfProviderMatch = false;
+    boolean collectionOfJavaxProvidersOfEntryOfProviderMatch = false;
+    List<Object> otherMapBindings = Lists.newArrayList();
+    List<Binding> otherMatches = Lists.newArrayList();
+    Multimap<Object, IndexedBinding> indexedEntries =
+        MultimapBuilder.hashKeys().hashSetValues().build();
+    Indexer indexer = new Indexer(injector);
+    int duplicates = 0;
+    for(Binding b : injector.getAllBindings().values()) {
+      boolean contains = mapbinder.containsElement(b);      
+      Object visited = b.acceptTargetVisitor(visitor);
+      if(visited instanceof MapBinderBinding) {
+        if(visited.equals(mapbinder)) {
+          assertTrue(contains);
+        } else {
+          otherMapBindings.add(visited);
+        }
+      } else if(b.getKey().equals(mapOfProvider)) {
+        assertTrue(contains);
+        mapProviderMatch = true;
+      } else if (b.getKey().equals(mapOfJavaxProvider)) {
+        assertTrue(contains);
+        mapJavaxProviderMatch = true;
+      } else if(b.getKey().equals(mapOfSet)) {
+        assertTrue(contains);
+        mapSetMatch = true;
+      } else if(b.getKey().equals(mapOfSetOfProvider)) {
+        assertTrue(contains);
+        mapSetProviderMatch = true;
+      } else if(b.getKey().equals(setOfEntry)) {
+        assertTrue(contains);
+        entrySetMatch = true;
+        // Validate that this binding is also a MultibinderBinding.
+        assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding);
+      } else if(b.getKey().equals(collectionOfProvidersOfEntryOfProvider)) {
+        assertTrue(contains);
+        collectionOfProvidersOfEntryOfProviderMatch = true;
+      } else if(b.getKey().equals(collectionOfJavaxProvidersOfEntryOfProvider)) {
+        assertTrue(contains);
+        collectionOfJavaxProvidersOfEntryOfProviderMatch = true;
+      } else if (contains) {
+        if (b instanceof ProviderInstanceBinding) {
+          ProviderInstanceBinding<?> pib = (ProviderInstanceBinding<?>)b;
+          if (pib.getUserSuppliedProvider() instanceof ProviderMapEntry) {
+            // weird casting required to workaround compilation issues with jdk6
+            ProviderMapEntry<?, ?> pme =
+                (ProviderMapEntry<?, ?>) (Provider) pib.getUserSuppliedProvider();
+            Binding<?> valueBinding = injector.getBinding(pme.getValueKey());
+            if (indexer.isIndexable(valueBinding)
+                && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) {
+              duplicates++;
+            }
+          }
+        }
+        otherMatches.add(b);
+      }
+    }
+    
+    int sizeOfOther = otherMatches.size();
+    if(allowDuplicates) {
+      sizeOfOther--; // account for 1 duplicate binding
+    }
+    // Multiply by two because each has a value and Map.Entry.
+    int expectedSize = 2 * (mapResults.size() + duplicates);
+    assertEquals("Incorrect other matches: " + otherMatches, expectedSize, sizeOfOther);
+    assertTrue(entrySetMatch);
+    assertTrue(mapProviderMatch);
+    assertTrue(mapJavaxProviderMatch);
+    assertTrue(collectionOfProvidersOfEntryOfProviderMatch);
+    assertTrue(collectionOfJavaxProvidersOfEntryOfProviderMatch);
+    assertEquals(allowDuplicates, mapSetMatch);
+    assertEquals(allowDuplicates, mapSetProviderMatch);
+    assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings,
+        otherMapBindings.size());
+  }
+  
+  @SuppressWarnings("unchecked")
+  private static <T> void mapModuleTest(Key<T> mapKey, TypeLiteral<?> keyType,
+      TypeLiteral<?> valueType, Iterable<? extends Module> modules, boolean allowDuplicates,
+      int expectedMapBindings, MapResult... results) {
+    Set<Element> elements = ImmutableSet.copyOf(Elements.getElements(modules));
+    Visitor<T> visitor = new Visitor<T>();
+    MapBinderBinding<T> mapbinder = null;
+    Map<Key<?>, Binding<?>> keyMap = Maps.newHashMap();
+    for(Element element : elements) {
+      if(element instanceof Binding) {
+        Binding<?> binding = (Binding<?>)element;
+        keyMap.put(binding.getKey(), binding);
+        if (binding.getKey().equals(mapKey)) {
+          mapbinder = (MapBinderBinding<T>)((Binding<T>)binding).acceptTargetVisitor(visitor);
+        }
+      }
+    }
+    assertNotNull(mapbinder);
+    
+    assertEquals(keyType, mapbinder.getKeyTypeLiteral());
+    assertEquals(valueType, mapbinder.getValueTypeLiteral());
+    List<MapResult> mapResults = Lists.newArrayList(results);
+    
+    Key<?> mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType));
+    Key<?> mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType));
+    Key<?> mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType));
+    Key<?> mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType)));
+    Key<?> setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType)));    
+    Key<?> collectionOfProvidersOfEntry =
+        mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType)));
+    Key<?> collectionOfJavaxProvidersOfEntry =
+        mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType)));
+    boolean entrySetMatch = false;
+    boolean mapProviderMatch = false;
+    boolean mapJavaxProviderMatch = false;
+    boolean mapSetMatch = false;
+    boolean mapSetProviderMatch = false;
+    boolean collectionOfProvidersOfEntryMatch = false;
+    boolean collectionOfJavaxProvidersOfEntryMatch = false;
+    List<Object> otherMapBindings = Lists.newArrayList();
+    List<Element> otherMatches = Lists.newArrayList();
+    List<Element> otherElements = Lists.newArrayList();
+    Indexer indexer = new Indexer(null);
+    Multimap<Object, IndexedBinding> indexedEntries =
+        MultimapBuilder.hashKeys().hashSetValues().build();
+    int duplicates = 0;
+    for(Element element : elements) {
+      boolean contains = mapbinder.containsElement(element);
+      if(!contains) {
+        otherElements.add(element);
+      }
+      boolean matched = false;
+      Key key = null;
+      Binding b = null;
+      if(element instanceof Binding) {
+        b = (Binding)element;
+        if (b instanceof ProviderInstanceBinding) {
+          ProviderInstanceBinding<?> pb = (ProviderInstanceBinding<?>) b;
+          if (pb.getUserSuppliedProvider() instanceof ProviderMapEntry) {
+            // weird casting required to workaround jdk6 compilation problems
+            ProviderMapEntry<?, ?> pme =
+                (ProviderMapEntry<?, ?>) (Provider) pb.getUserSuppliedProvider();
+            Binding<?> valueBinding = keyMap.get(pme.getValueKey());
+            if (indexer.isIndexable(valueBinding)
+                && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) {
+              duplicates++;
+            }
+          }
+        }
+
+        key = b.getKey();
+        Object visited = b.acceptTargetVisitor(visitor);
+        if(visited instanceof MapBinderBinding) {
+          matched = true;
+          if(visited.equals(mapbinder)) {
+            assertTrue(contains);
+          } else {
+            otherMapBindings.add(visited);
+          }
+        }
+      } else if(element instanceof ProviderLookup) {
+        key = ((ProviderLookup)element).getKey();
+      }
+      
+      if(!matched && key != null) {
+        if(key.equals(mapOfProvider)) {
+          matched = true;
+          assertTrue(contains);
+          mapProviderMatch = true;
+        } else if(key.equals(mapOfJavaxProvider)) {
+          matched = true;
+          assertTrue(contains);
+          mapJavaxProviderMatch = true;
+        } else if(key.equals(mapOfSet)) {
+          matched = true;
+          assertTrue(contains);
+          mapSetMatch = true;
+        } else if(key.equals(mapOfSetOfProvider)) {
+          matched = true;
+          assertTrue(contains);
+          mapSetProviderMatch = true;
+        } else if(key.equals(setOfEntry)) {
+          matched = true;
+          assertTrue(contains);
+          entrySetMatch = true;
+          // Validate that this binding is also a MultibinderBinding.
+          if(b != null) {
+            assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding);
+          }
+        } else if(key.equals(collectionOfProvidersOfEntry)) {
+          matched = true;
+          assertTrue(contains);
+          collectionOfProvidersOfEntryMatch = true;
+        } else if(key.equals(collectionOfJavaxProvidersOfEntry)) {
+          matched = true;
+          assertTrue(contains);
+          collectionOfJavaxProvidersOfEntryMatch = true;
+        }
+      }
+      
+      if (!matched && contains) {
+        otherMatches.add(element);
+      }
+    }
+    
+    int otherMatchesSize = otherMatches.size();
+    if (allowDuplicates) {
+      otherMatchesSize--; // allow for 1 duplicate binding
+    }
+    // Multiply by 3 because each has a value, ProviderLookup, and Map.Entry
+    int expectedSize = (mapResults.size() + duplicates) * 3;
+    assertEquals("incorrect number of contains, leftover matches: " + otherMatches,
+        expectedSize, otherMatchesSize);
+
+    assertTrue(entrySetMatch);
+    assertTrue(mapProviderMatch);
+    assertTrue(mapJavaxProviderMatch);
+    assertTrue(collectionOfProvidersOfEntryMatch);
+    assertTrue(collectionOfJavaxProvidersOfEntryMatch);
+    assertEquals(allowDuplicates, mapSetMatch);
+    assertEquals(allowDuplicates, mapSetProviderMatch);
+    assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings,
+        otherMapBindings.size());
+    
+     // Validate that we can construct an injector out of the remaining bindings.
+    Guice.createInjector(Elements.getModule(otherElements));
+  }
+  
+  /**
+   * Asserts that MultibinderBinding visitors work correctly.
+   * 
+   * @param <T> The type of the binding
+   * @param setKey The key the set belongs to.
+   * @param elementType the TypeLiteral of the element
+   * @param modules The modules that define the multibindings
+   * @param visitType The kind of test we should perform.  A live Injector, a raw Elements (Module) test, or both.
+   * @param allowDuplicates If duplicates are allowed.
+   * @param expectedMultibindings The number of other multibinders we expect to see.
+   * @param results The kind of bindings contained in the multibinder.
+   */
+  static <T> void assertSetVisitor(Key<Set<T>> setKey, TypeLiteral<?> elementType,
+      Iterable<? extends Module> modules, VisitType visitType, boolean allowDuplicates,
+      int expectedMultibindings, BindResult... results) {
+    if(visitType == null) {
+      fail("must test something");
+    }
+    
+    if(visitType == BOTH || visitType == INJECTOR) {
+      setInjectorTest(setKey, elementType, modules, allowDuplicates,
+          expectedMultibindings, results);
+    }
+    
+    if(visitType == BOTH || visitType == MODULE) {
+      setModuleTest(setKey, elementType, modules, allowDuplicates,
+          expectedMultibindings, results);
+    }
+  }
+  
+  @SuppressWarnings("unchecked")
+  private static <T> void setInjectorTest(Key<Set<T>> setKey, TypeLiteral<?> elementType,
+      Iterable<? extends Module> modules, boolean allowDuplicates, int otherMultibindings,
+      BindResult... results) {
+    Key<?> collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType));
+    Key<?> collectionOfJavaxProvidersKey =
+        setKey.ofType(collectionOfJavaxProvidersOf(elementType));
+    Injector injector = Guice.createInjector(modules);
+    Visitor<Set<T>> visitor = new Visitor<Set<T>>();
+    Binding<Set<T>> binding = injector.getBinding(setKey);
+    MultibinderBinding<Set<T>> multibinder =
+        (MultibinderBinding<Set<T>>)binding.acceptTargetVisitor(visitor);
+    assertNotNull(multibinder);
+    assertEquals(elementType, multibinder.getElementTypeLiteral());
+    assertEquals(allowDuplicates, multibinder.permitsDuplicates());
+    List<Binding<?>> elements = Lists.newArrayList(multibinder.getElements());
+    List<BindResult> bindResults = Lists.newArrayList(results);
+    assertEquals("wrong bind elements, expected: " + bindResults
+        + ", but was: " + multibinder.getElements(),
+        bindResults.size(), elements.size());
+
+    for(BindResult result : bindResults) {
+      Binding found = null;
+      for(Binding item : elements) {
+        if (matches(item, result)) {
+          found = item;
+          break;
+        }
+      }
+      if(found == null) {
+        fail("Could not find element: " + result + " in remaining elements: " + elements);
+      } else {
+        elements.remove(found);
+      }
+    }
+    
+    if(!elements.isEmpty()) {
+      fail("Found all elements of: " + bindResults + ", but more were left over: " + elements);
+    }
+
+    Set<Binding> setOfElements = new HashSet<Binding>(multibinder.getElements()); 
+    Set<IndexedBinding> setOfIndexed = Sets.newHashSet();
+    Indexer indexer = new Indexer(injector);
+    for (Binding<?> oneBinding : setOfElements) {
+      setOfIndexed.add(oneBinding.acceptTargetVisitor(indexer));
+    }
+
+    List<Object> otherMultibinders = Lists.newArrayList();
+    List<Binding> otherContains = Lists.newArrayList();
+    boolean collectionOfProvidersMatch = false;
+    boolean collectionOfJavaxProvidersMatch = false;
+    for(Binding b : injector.getAllBindings().values()) {
+      boolean contains = multibinder.containsElement(b);
+      Key key = b.getKey();
+      Object visited = b.acceptTargetVisitor(visitor);
+      if(visited != null) {
+        if(visited.equals(multibinder)) {
+          assertTrue(contains);
+        } else {
+          otherMultibinders.add(visited);
+        }
+      } else if(setOfElements.contains(b)) {
+        assertTrue(contains);
+      } else if (key.equals(collectionOfProvidersKey)) {
+        assertTrue(contains);
+        collectionOfProvidersMatch = true;
+      } else if (key.equals(collectionOfJavaxProvidersKey)) {
+        assertTrue(contains);
+        collectionOfJavaxProvidersMatch = true;
+      } else if (contains) {
+        if (!indexer.isIndexable(b) || !setOfIndexed.contains(b.acceptTargetVisitor(indexer))) {
+          otherContains.add(b);
+        }
+      }
+    }
+
+    assertTrue(collectionOfProvidersMatch);
+    assertTrue(collectionOfJavaxProvidersMatch);
+
+    if(allowDuplicates) {
+      assertEquals("contained more than it should: " + otherContains, 1, otherContains.size());
+    } else {
+      assertTrue("contained more than it should: " + otherContains, otherContains.isEmpty());
+    }
+    assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings,
+        otherMultibinders.size());
+    
+  }
+  
+  @SuppressWarnings("unchecked")
+  private static <T> void setModuleTest(Key<Set<T>> setKey, TypeLiteral<?> elementType,
+      Iterable<? extends Module> modules, boolean allowDuplicates, int otherMultibindings,
+      BindResult... results) {
+    Key<?> collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType));
+    Key<?> collectionOfJavaxProvidersKey =
+        setKey.ofType(collectionOfJavaxProvidersOf(elementType));
+    List<BindResult> bindResults = Lists.newArrayList(results);
+    List<Element> elements = Elements.getElements(modules);
+    Visitor<T> visitor = new Visitor<T>();
+    MultibinderBinding<Set<T>> multibinder = null;
+    for(Element element : elements) {
+      if(element instanceof Binding && ((Binding)element).getKey().equals(setKey)) {
+        multibinder = (MultibinderBinding<Set<T>>)((Binding)element).acceptTargetVisitor(visitor);
+        break;
+      }
+    }
+    assertNotNull(multibinder);
+
+    assertEquals(elementType, multibinder.getElementTypeLiteral());
+    List<Object> otherMultibinders = Lists.newArrayList();
+    Set<Element> otherContains = new HashSet<Element>();
+    List<Element> otherElements = Lists.newArrayList();
+    int duplicates = 0;
+    Set<IndexedBinding> setOfIndexed = Sets.newHashSet();
+    Indexer indexer = new Indexer(null);
+    boolean collectionOfProvidersMatch = false;
+    boolean collectionOfJavaxProvidersMatch = false;
+    for(Element element : elements) {
+      boolean contains = multibinder.containsElement(element);
+      if(!contains) {
+        otherElements.add(element);
+      }
+      boolean matched = false;
+      Key key = null;
+      if(element instanceof Binding) {
+        Binding binding = (Binding)element;
+        if (indexer.isIndexable(binding)
+            && !setOfIndexed.add((IndexedBinding) binding.acceptTargetVisitor(indexer))) {
+          duplicates++;
+        }
+        key = binding.getKey();
+        Object visited = binding.acceptTargetVisitor(visitor);
+        if(visited != null) {
+          matched = true;
+          if(visited.equals(multibinder)) {
+            assertTrue(contains);
+          } else {
+            otherMultibinders.add(visited);
+          }
+        }
+      }
+
+      if (collectionOfProvidersKey.equals(key)) {
+        assertTrue(contains);
+        assertFalse(matched);
+        collectionOfProvidersMatch = true;
+      } else if (collectionOfJavaxProvidersKey.equals(key)) {
+          assertTrue(contains);
+          assertFalse(matched);
+          collectionOfJavaxProvidersMatch = true;
+      } else if (!matched && contains) {
+        otherContains.add(element);
+      }
+    }
+
+    if(allowDuplicates) {
+      assertEquals("wrong contained elements: " + otherContains,
+          bindResults.size() + 1 + duplicates, otherContains.size());
+    } else {
+      assertEquals("wrong contained elements: " + otherContains,
+          bindResults.size() + duplicates, otherContains.size());
+    }
+
+    assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings,
+        otherMultibinders.size());
+    assertTrue(collectionOfProvidersMatch);
+    assertTrue(collectionOfJavaxProvidersMatch);
+
+    // Validate that we can construct an injector out of the remaining bindings.
+    Guice.createInjector(Elements.getModule(otherElements));
+  }
+
+  /**
+   * Asserts that OptionalBinderBinding visitors for work correctly.
+   *
+   * @param <T> The type of the binding
+   * @param keyType The key OptionalBinder is binding
+   * @param modules The modules that define the bindings
+   * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module)
+   *        test, or both.
+   * @param expectedOtherOptionalBindings the # of other optional bindings we expect to see.
+   * @param expectedDefault the expected default binding, or null if none
+   * @param expectedActual the expected actual binding, or null if none
+   * @param expectedUserLinkedActual the user binding that is the actual binding, used if
+   *        neither the default nor actual are set and a user binding existed for the type.
+   */
+  static <T> void assertOptionalVisitor(Key<T> keyType,
+      Iterable<? extends Module> modules,
+      VisitType visitType,
+      int expectedOtherOptionalBindings,
+      BindResult<?> expectedDefault,
+      BindResult<?> expectedActual,
+      BindResult<?> expectedUserLinkedActual) {
+    if (visitType == null) {
+      fail("must test something");
+    }
+
+    // if java.util.Optional is bound, there'll be twice as many as we expect.
+    if (HAS_JAVA_OPTIONAL) {
+      expectedOtherOptionalBindings *= 2;
+    }
+
+    if (visitType == BOTH || visitType == INJECTOR) {
+      optionalInjectorTest(keyType, modules, expectedOtherOptionalBindings, expectedDefault,
+          expectedActual, expectedUserLinkedActual);
+    }
+
+    if (visitType == BOTH || visitType == MODULE) {
+      optionalModuleTest(keyType, modules, expectedOtherOptionalBindings, expectedDefault,
+          expectedActual, expectedUserLinkedActual);
+    }
+  }
+
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  private static <T> void optionalInjectorTest(Key<T> keyType,
+      Iterable<? extends Module> modules,
+      int expectedOtherOptionalBindings,
+      BindResult<?> expectedDefault,
+      BindResult<?> expectedActual,
+      BindResult<?> expectedUserLinkedActual) {
+    if (expectedUserLinkedActual != null) {
+      assertNull("cannot have actual if expecting user binding", expectedActual);
+      assertNull("cannot have default if expecting user binding", expectedDefault);
+    }
+
+    Key<Optional<T>> optionalKey =
+        keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral()));
+    Key<?> javaOptionalKey = HAS_JAVA_OPTIONAL ?
+        keyType.ofType(OptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) : null;
+    Injector injector = Guice.createInjector(modules);
+    Binding<Optional<T>> optionalBinding = injector.getBinding(optionalKey);
+    Visitor visitor = new Visitor();
+    OptionalBinderBinding<Optional<T>> optionalBinder =
+        (OptionalBinderBinding<Optional<T>>) optionalBinding.acceptTargetVisitor(visitor);
+    assertNotNull(optionalBinder);
+    assertEquals(optionalKey, optionalBinder.getKey());
+
+    Binding<?> javaOptionalBinding = null;
+    OptionalBinderBinding<?> javaOptionalBinder = null;
+    if (HAS_JAVA_OPTIONAL) {
+      javaOptionalBinding = injector.getBinding(javaOptionalKey);
+      javaOptionalBinder = (OptionalBinderBinding<?>) javaOptionalBinding.acceptTargetVisitor(visitor);
+      assertNotNull(javaOptionalBinder);
+      assertEquals(javaOptionalKey, javaOptionalBinder.getKey());
+    }
+
+    if (expectedDefault == null) {
+      assertNull("did not expect a default binding", optionalBinder.getDefaultBinding());
+      if (HAS_JAVA_OPTIONAL) {
+        assertNull("did not expect a default binding", javaOptionalBinder.getDefaultBinding());  
+      }
+    } else {
+      assertTrue("expectedDefault: " + expectedDefault + ", actualDefault: "
+              + optionalBinder.getDefaultBinding(),
+          matches(optionalBinder.getDefaultBinding(), expectedDefault));
+      if (HAS_JAVA_OPTIONAL) {
+        assertTrue("expectedDefault: " + expectedDefault + ", actualDefault: "
+                + javaOptionalBinder.getDefaultBinding(),
+            matches(javaOptionalBinder.getDefaultBinding(), expectedDefault));
+      }
+    }
+
+    if (expectedActual == null && expectedUserLinkedActual == null) {
+      assertNull(optionalBinder.getActualBinding());
+      if (HAS_JAVA_OPTIONAL) {
+        assertNull(javaOptionalBinder.getActualBinding());  
+      }
+    } else if (expectedActual != null) {
+      assertTrue("expectedActual: " + expectedActual + ", actualActual: "
+              + optionalBinder.getActualBinding(),
+          matches(optionalBinder.getActualBinding(), expectedActual));
+      if (HAS_JAVA_OPTIONAL) {
+        assertTrue("expectedActual: " + expectedActual + ", actualActual: "
+                + javaOptionalBinder.getActualBinding(),
+            matches(javaOptionalBinder.getActualBinding(), expectedActual));
+      }
+    } else if (expectedUserLinkedActual != null) {
+      assertTrue("expectedUserLinkedActual: " + expectedUserLinkedActual + ", actualActual: "
+              + optionalBinder.getActualBinding(),
+          matches(optionalBinder.getActualBinding(), expectedUserLinkedActual));
+      if (HAS_JAVA_OPTIONAL) {
+        assertTrue("expectedUserLinkedActual: " + expectedUserLinkedActual + ", actualActual: "
+                + javaOptionalBinder.getActualBinding(),
+            matches(javaOptionalBinder.getActualBinding(), expectedUserLinkedActual));  
+      }
+    }
+
+
+    Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey =
+        keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral()));
+    Key<?> javaOptionalJavaxProviderKey = HAS_JAVA_OPTIONAL ?
+        keyType.ofType(javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) : null;
+    Key<Optional<Provider<T>>> optionalProviderKey =
+        keyType.ofType(optionalOfProvider(keyType.getTypeLiteral()));
+    Key<?> javaOptionalProviderKey = HAS_JAVA_OPTIONAL ?
+        keyType.ofType(javaOptionalOfProvider(keyType.getTypeLiteral())) : null;
+
+    boolean keyMatch = false;
+    boolean optionalKeyMatch = false;
+    boolean javaOptionalKeyMatch = false;
+    boolean optionalJavaxProviderKeyMatch = false;
+    boolean javaOptionalJavaxProviderKeyMatch = false;
+    boolean optionalProviderKeyMatch = false;
+    boolean javaOptionalProviderKeyMatch = false;
+    boolean defaultMatch = false;
+    boolean actualMatch = false;
+    List<Object> otherOptionalBindings = Lists.newArrayList();
+    List<Binding> otherMatches = Lists.newArrayList();
+    for (Binding b : injector.getAllBindings().values()) {
+      boolean contains = optionalBinder.containsElement(b);
+      if (HAS_JAVA_OPTIONAL) {
+        assertEquals(contains, javaOptionalBinder.containsElement(b));
+      }
+      Object visited = b.acceptTargetVisitor(visitor);
+      if (visited instanceof OptionalBinderBinding) {
+        if (visited.equals(optionalBinder)) {
+          assertTrue(contains);
+        } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) {
+          assertTrue(contains);
+        } else {
+          otherOptionalBindings.add(visited);
+        }
+      }
+      if (b.getKey().equals(keyType)) {
+        // keyType might match because a user bound it
+        // (which is possible in a purely absent OptionalBinder)
+        assertEquals(expectedDefault != null || expectedActual != null, contains);
+        if (contains) {
+          keyMatch = true;
+        }
+      } else if (b.getKey().equals(optionalKey)) {
+        assertTrue(contains);
+        optionalKeyMatch = true;
+      } else if (b.getKey().equals(javaOptionalKey)) {
+        assertTrue(contains);
+        javaOptionalKeyMatch = true;
+      } else if (b.getKey().equals(optionalJavaxProviderKey)) {
+        assertTrue(contains);
+        optionalJavaxProviderKeyMatch = true;
+      } else if (b.getKey().equals(javaOptionalJavaxProviderKey)) {
+        assertTrue(contains);
+        javaOptionalJavaxProviderKeyMatch = true;
+      } else if (b.getKey().equals(optionalProviderKey)) {
+        assertTrue(contains);
+        optionalProviderKeyMatch = true;
+      } else if (b.getKey().equals(javaOptionalProviderKey)) {
+        assertTrue(contains);
+        javaOptionalProviderKeyMatch = true;
+      } else if (expectedDefault != null && matches(b, expectedDefault)) {
+        assertTrue(contains);
+        defaultMatch = true;
+      } else if (expectedActual != null && matches(b, expectedActual)) {
+        assertTrue(contains);
+        actualMatch = true;
+      } else if (contains) {
+        otherMatches.add(b);
+      }
+    }
+
+    assertEquals(otherMatches.toString(), 0, otherMatches.size());
+    // only expect a keymatch if either default or actual are set
+    assertEquals(expectedDefault != null || expectedActual != null, keyMatch);
+    assertTrue(optionalKeyMatch);
+    assertTrue(optionalJavaxProviderKeyMatch);
+    assertTrue(optionalProviderKeyMatch);
+    assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch);
+    assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch);
+    assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch);
+    assertEquals(expectedDefault != null, defaultMatch);
+    assertEquals(expectedActual != null, actualMatch);
+    assertEquals("other OptionalBindings found: " + otherOptionalBindings,
+        expectedOtherOptionalBindings, otherOptionalBindings.size());
+  }
+
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  private static <T> void optionalModuleTest(Key<T> keyType,
+      Iterable<? extends Module> modules,
+      int expectedOtherOptionalBindings,
+      BindResult<?> expectedDefault,
+      BindResult<?> expectedActual,
+      BindResult<?> expectedUserLinkedActual) {
+    if (expectedUserLinkedActual != null) {
+      assertNull("cannot have actual if expecting user binding", expectedActual);
+      assertNull("cannot have default if expecting user binding", expectedDefault);
+    }
+    Set<Element> elements = ImmutableSet.copyOf(Elements.getElements(modules));
+    Map<Key<?>, Binding<?>> indexed = index(elements);
+    Key<Optional<T>> optionalKey =
+        keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral()));
+    Key<?> javaOptionalKey = HAS_JAVA_OPTIONAL ?
+        keyType.ofType(OptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) : null;
+    Visitor visitor = new Visitor();
+    OptionalBinderBinding<Optional<T>> optionalBinder = null;
+    OptionalBinderBinding<?> javaOptionalBinder = null;
+    Key<?> defaultKey = null;
+    Key<?> actualKey = null;
+
+    Binding optionalBinding = indexed.get(optionalKey);
+    optionalBinder =
+        (OptionalBinderBinding<Optional<T>>) optionalBinding.acceptTargetVisitor(visitor);
+
+    if (HAS_JAVA_OPTIONAL) {
+      Binding javaOptionalBinding = indexed.get(javaOptionalKey);
+      javaOptionalBinder = (OptionalBinderBinding) javaOptionalBinding.acceptTargetVisitor(visitor);
+    }
+
+    // Locate the defaultKey & actualKey
+    for (Element element : elements) {
+      if (optionalBinder.containsElement(element) && element instanceof Binding) {
+        Binding binding = (Binding) element;
+        if (isSourceEntry(binding, Source.DEFAULT)) {
+          defaultKey = binding.getKey();
+        } else if (isSourceEntry(binding, Source.ACTUAL)) {
+          actualKey = binding.getKey();
+        }
+      }
+    }
+    assertNotNull(optionalBinder);
+    if (HAS_JAVA_OPTIONAL) {
+      assertNotNull(javaOptionalBinder);
+    }
+    assertEquals(expectedDefault == null, defaultKey == null);
+    assertEquals(expectedActual == null, actualKey == null);
+
+    Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey =
+        keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral()));
+    Key<?> javaOptionalJavaxProviderKey = HAS_JAVA_OPTIONAL ?
+        keyType.ofType(javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) : null;
+    Key<Optional<Provider<T>>> optionalProviderKey =
+        keyType.ofType(optionalOfProvider(keyType.getTypeLiteral()));
+    Key<?> javaOptionalProviderKey = HAS_JAVA_OPTIONAL ?
+        keyType.ofType(javaOptionalOfProvider(keyType.getTypeLiteral())) : null;
+    boolean keyMatch = false;
+    boolean optionalKeyMatch = false;
+    boolean javaOptionalKeyMatch = false;
+    boolean optionalJavaxProviderKeyMatch = false;
+    boolean javaOptionalJavaxProviderKeyMatch = false;
+    boolean optionalProviderKeyMatch = false;
+    boolean javaOptionalProviderKeyMatch = false;
+    boolean defaultMatch = false;
+    boolean actualMatch = false;
+    List<Object> otherOptionalElements = Lists.newArrayList();
+    List<Element> otherContains = Lists.newArrayList();
+    List<Element> nonContainedElements = Lists.newArrayList();
+    for (Element element : elements) {
+      boolean contains = optionalBinder.containsElement(element);
+      if (HAS_JAVA_OPTIONAL) {
+        assertEquals(contains, javaOptionalBinder.containsElement(element));
+      }
+      if (!contains) {
+        nonContainedElements.add(element);
+      }
+      Key key = null;
+      Binding b = null;
+      if (element instanceof Binding) {
+        b = (Binding) element;
+        key = b.getKey();
+        Object visited = b.acceptTargetVisitor(visitor);
+        if (visited instanceof OptionalBinderBinding) {
+          if (visited.equals(optionalBinder)) {
+            assertTrue(contains);
+          } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) {
+            assertTrue(contains);
+          } else {
+            otherOptionalElements.add(visited);
+          }
+        }
+      } else if (element instanceof ProviderLookup) {
+        key = ((ProviderLookup) element).getKey();
+      }
+
+      if (key != null && key.equals(keyType)) {
+        // keyType might match because a user bound it
+        // (which is possible in a purely absent OptionalBinder)
+        assertEquals(expectedDefault != null || expectedActual != null, contains);
+        if (contains) {
+          keyMatch = true;
+        }
+      } else if (key != null && key.equals(optionalKey)) {
+        assertTrue(contains);
+        optionalKeyMatch = true;
+      } else if (key != null && key.equals(javaOptionalKey)) {
+        assertTrue(contains);
+        javaOptionalKeyMatch = true;
+      } else if (key != null && key.equals(optionalJavaxProviderKey)) {
+        assertTrue(contains);
+        optionalJavaxProviderKeyMatch = true;
+      } else if (key != null && key.equals(javaOptionalJavaxProviderKey)) {
+        assertTrue(contains);
+        javaOptionalJavaxProviderKeyMatch = true;
+      } else if (key != null && key.equals(optionalProviderKey)) {
+        assertTrue(contains);
+        optionalProviderKeyMatch = true;
+      } else if (key != null && key.equals(javaOptionalProviderKey)) {
+        assertTrue(contains);
+        javaOptionalProviderKeyMatch = true;
+      } else if (key != null && key.equals(defaultKey)) {
+        assertTrue(contains);
+        if (b != null) { // otherwise it might just be a ProviderLookup into it
+          assertTrue("expected: " + expectedDefault + ", but was: " + b,
+              matches(b, expectedDefault));
+          defaultMatch = true;
+        }
+      } else if (key != null && key.equals(actualKey)) {
+        assertTrue(contains);
+        if (b != null) { // otherwise it might just be a ProviderLookup into it
+          assertTrue("expected: " + expectedActual + ", but was: " + b, matches(b, expectedActual));
+          actualMatch = true;
+        }
+      } else if (contains) {
+        otherContains.add(element);
+      }
+    }
+    
+    // only expect a keymatch if either default or actual are set
+    assertEquals(expectedDefault != null || expectedActual != null, keyMatch);
+    assertTrue(optionalKeyMatch);
+    assertTrue(optionalJavaxProviderKeyMatch);
+    assertTrue(optionalProviderKeyMatch);
+    assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch);
+    assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch);
+    assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch);
+    assertEquals(expectedDefault != null, defaultMatch);
+    assertEquals(expectedActual != null, actualMatch);
+    assertEquals(otherContains.toString(), 0, otherContains.size());
+    assertEquals("other OptionalBindings found: " + otherOptionalElements,
+        expectedOtherOptionalBindings, otherOptionalElements.size());
+    
+     // Validate that we can construct an injector out of the remaining bindings.
+    Guice.createInjector(Elements.getModule(nonContainedElements));
+  }
+
+  private static boolean isSourceEntry(Binding b, Source type) {
+    switch(type) {
+      case ACTUAL:
+        return b.getKey().getAnnotation() instanceof OptionalBinder.Actual;
+      case DEFAULT:
+        return b.getKey().getAnnotation() instanceof OptionalBinder.Default;
+      default:
+        throw new IllegalStateException("invalid type: " + type);
+    }
+  }
+
+  /** Returns the subset of elements that have keys, indexed by them. */
+  private static Map<Key<?>, Binding<?>> index(Iterable<Element> elements) {
+    ImmutableMap.Builder<Key<?>, Binding<?>> builder = ImmutableMap.builder();
+    for (Element element : elements) {
+      if (element instanceof Binding) {
+        builder.put(((Binding) element).getKey(), (Binding) element);
+      }
+    }
+    return builder.build();
+  }
+  
+  static <K, V> MapResult instance(K k, V v) {
+    return new MapResult<K, V>(k, new BindResult<V>(INSTANCE, v, null));
+  }
+
+  static <K, V> MapResult linked(K k, Class<? extends V> clazz) {
+    return new MapResult<K, V>(k, new BindResult<V>(LINKED, null, Key.get(clazz)));
+  }
+
+  static <K, V> MapResult linked(K k, Key<? extends V> key) {
+    return new MapResult<K, V>(k, new BindResult<V>(LINKED, null, key));
+  }
+
+  static <K, V> MapResult providerInstance(K k, V v) {
+    return new MapResult<K, V>(k, new BindResult<V>(PROVIDER_INSTANCE, v, null));
+  }
+
+  static class MapResult<K, V> {
+    private final K k;
+    private final BindResult<V> v;
+    
+    MapResult(K k, BindResult<V> v) {
+      this.k = k;
+      this.v = v;
+    }
+    
+    @Override
+    public String toString() {
+      return "entry[key[" + k + "],value[" + v + "]]";
+    }
+  }  
+  
+  private static boolean matches(Binding<?> item, BindResult<?> result) {
+    switch (result.type) {
+    case INSTANCE:
+      if (item instanceof InstanceBinding
+          && ((InstanceBinding) item).getInstance().equals(result.instance)) {
+        return true;
+      }
+      break;
+    case LINKED:
+      if (item instanceof LinkedKeyBinding
+          && ((LinkedKeyBinding) item).getLinkedKey().equals(result.key)) {
+        return true;
+      }
+      break;
+    case PROVIDER_INSTANCE:
+      if (item instanceof ProviderInstanceBinding
+          && Objects.equal(((ProviderInstanceBinding) item).getUserSuppliedProvider().get(),
+                           result.instance)) {
+        return true;
+      }
+      break;
+    case PROVIDER_KEY:
+      if (item instanceof ProviderKeyBinding
+          && ((ProviderKeyBinding) item).getProviderKey().equals(result.key)) {
+        return true;
+      }
+      break;
+    }
+    return false;
+  }
+
+  static <T> BindResult<T> instance(T t) {
+    return new BindResult<T>(INSTANCE, t, null);
+  }
+
+  static <T> BindResult<T> linked(Class<? extends T> clazz) {
+    return new BindResult<T>(LINKED, null, Key.get(clazz));
+  }
+
+  static <T> BindResult<T> linked(Key<? extends T> key) {
+    return new BindResult<T>(LINKED, null, key);
+  }
+
+  static <T> BindResult<T> providerInstance(T t) {
+    return new BindResult<T>(PROVIDER_INSTANCE, t, null);
+  }
+
+  static <T> BindResult<T> providerKey(Key<T> key) {
+    return new BindResult<T>(PROVIDER_KEY, null, key);
+  }
+  
+  /** The kind of binding. */
+  static enum BindType { INSTANCE, LINKED, PROVIDER_INSTANCE, PROVIDER_KEY }
+  /** The result of the binding. */
+  static class BindResult<T> {
+    private final BindType type;
+    private final Key<?> key;
+    private final T instance;
+    
+    private BindResult(BindType type, T instance, Key<?> key) {
+      this.type = type;
+      this.instance = instance;
+      this.key = key;
+    }
+    
+    @Override
+    public String toString() {
+      switch(type) {
+      case INSTANCE:
+        return "instance[" + instance + "]";
+      case LINKED:
+        return "linkedKey[" + key + "]";
+      case PROVIDER_INSTANCE:
+        return "providerInstance[" + instance + "]";
+      case PROVIDER_KEY:
+        return "providerKey[" + key + "]";
+      }
+      return null;
+    }
+  }
+  
+  private static class Visitor<T> extends
+      DefaultBindingTargetVisitor<T, Object> implements MultibindingsTargetVisitor<T, Object> {
+  
+    public Object visit(MultibinderBinding<? extends T> multibinding) {
+      return multibinding;
+    }
+  
+    public Object visit(MapBinderBinding<? extends T> mapbinding) {
+      return mapbinding;
+    }
+    
+    public Object visit(OptionalBinderBinding<? extends T> optionalbinding) {
+      return optionalbinding;
+    }
+  }
+}
diff --git a/extensions/persist/build.properties b/extensions/persist/build.properties
new file mode 100644
index 0000000..4d4504d
--- /dev/null
+++ b/extensions/persist/build.properties
@@ -0,0 +1,8 @@
+lib.dir=../../lib
+ext.lib.dir=lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.persist.AllTests
+module=com.google.inject.persist
+fragment=true
diff --git a/extensions/persist/build.xml b/extensions/persist/build.xml
new file mode 100644
index 0000000..3cc6a4f
--- /dev/null
+++ b/extensions/persist/build.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+
+<project name="guice-persist" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+  	<fileset dir="${ext.lib.dir}" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/persist/lib/antlr-2.7.5h3.jar b/extensions/persist/lib/antlr-2.7.5h3.jar
new file mode 100644
index 0000000..d02328e
--- /dev/null
+++ b/extensions/persist/lib/antlr-2.7.5h3.jar
Binary files differ
diff --git a/extensions/persist/lib/aopalliance.jar b/extensions/persist/lib/aopalliance.jar
new file mode 100644
index 0000000..578b1a0
--- /dev/null
+++ b/extensions/persist/lib/aopalliance.jar
Binary files differ
diff --git a/extensions/persist/lib/cglib-nodep-3.0.jar b/extensions/persist/lib/cglib-nodep-3.0.jar
new file mode 100644
index 0000000..1f761af
--- /dev/null
+++ b/extensions/persist/lib/cglib-nodep-3.0.jar
Binary files differ
diff --git a/extensions/persist/lib/commons-collections.jar b/extensions/persist/lib/commons-collections.jar
new file mode 100644
index 0000000..75580be
--- /dev/null
+++ b/extensions/persist/lib/commons-collections.jar
Binary files differ
diff --git a/extensions/persist/lib/commons-io.jar b/extensions/persist/lib/commons-io.jar
new file mode 100644
index 0000000..624fc1a
--- /dev/null
+++ b/extensions/persist/lib/commons-io.jar
Binary files differ
diff --git a/extensions/persist/lib/commons-logging-1.0.4.jar b/extensions/persist/lib/commons-logging-1.0.4.jar
new file mode 100644
index 0000000..b73a80f
--- /dev/null
+++ b/extensions/persist/lib/commons-logging-1.0.4.jar
Binary files differ
diff --git a/extensions/persist/lib/db4o-6.4.14.8131-java5.jar b/extensions/persist/lib/db4o-6.4.14.8131-java5.jar
new file mode 100644
index 0000000..8422fde
--- /dev/null
+++ b/extensions/persist/lib/db4o-6.4.14.8131-java5.jar
Binary files differ
diff --git a/extensions/persist/lib/dom4j-1.6.1.jar b/extensions/persist/lib/dom4j-1.6.1.jar
new file mode 100644
index 0000000..c8c4dbb
--- /dev/null
+++ b/extensions/persist/lib/dom4j-1.6.1.jar
Binary files differ
diff --git a/extensions/persist/lib/easymock.jar b/extensions/persist/lib/easymock.jar
new file mode 100644
index 0000000..6665bf1
--- /dev/null
+++ b/extensions/persist/lib/easymock.jar
Binary files differ
diff --git a/extensions/persist/lib/ejb3-persistence.jar b/extensions/persist/lib/ejb3-persistence.jar
new file mode 100644
index 0000000..3a896db
--- /dev/null
+++ b/extensions/persist/lib/ejb3-persistence.jar
Binary files differ
diff --git a/extensions/persist/lib/hibernate-annotations.jar b/extensions/persist/lib/hibernate-annotations.jar
new file mode 100644
index 0000000..d476493
--- /dev/null
+++ b/extensions/persist/lib/hibernate-annotations.jar
Binary files differ
diff --git a/extensions/persist/lib/hibernate-entitymanager.jar b/extensions/persist/lib/hibernate-entitymanager.jar
new file mode 100644
index 0000000..fd761bb
--- /dev/null
+++ b/extensions/persist/lib/hibernate-entitymanager.jar
Binary files differ
diff --git a/extensions/persist/lib/hibernate-search.jar b/extensions/persist/lib/hibernate-search.jar
new file mode 100644
index 0000000..9c3b5f2
--- /dev/null
+++ b/extensions/persist/lib/hibernate-search.jar
Binary files differ
diff --git a/extensions/persist/lib/hibernate3.jar b/extensions/persist/lib/hibernate3.jar
new file mode 100644
index 0000000..b600972
--- /dev/null
+++ b/extensions/persist/lib/hibernate3.jar
Binary files differ
diff --git a/extensions/persist/lib/hsqldb.jar b/extensions/persist/lib/hsqldb.jar
new file mode 100644
index 0000000..35436d6
--- /dev/null
+++ b/extensions/persist/lib/hsqldb.jar
Binary files differ
diff --git a/extensions/persist/lib/javassist.jar b/extensions/persist/lib/javassist.jar
new file mode 100644
index 0000000..d834b3a
--- /dev/null
+++ b/extensions/persist/lib/javassist.jar
Binary files differ
diff --git a/extensions/persist/lib/jaxen-1.1-beta-7.jar b/extensions/persist/lib/jaxen-1.1-beta-7.jar
new file mode 100644
index 0000000..c773f85
--- /dev/null
+++ b/extensions/persist/lib/jaxen-1.1-beta-7.jar
Binary files differ
diff --git a/extensions/persist/lib/jboss-archive-browsing.jar b/extensions/persist/lib/jboss-archive-browsing.jar
new file mode 100644
index 0000000..5af0ec4
--- /dev/null
+++ b/extensions/persist/lib/jboss-archive-browsing.jar
Binary files differ
diff --git a/extensions/persist/lib/jta.jar b/extensions/persist/lib/jta.jar
new file mode 100644
index 0000000..705e8c8
--- /dev/null
+++ b/extensions/persist/lib/jta.jar
Binary files differ
diff --git a/extensions/persist/lib/log4j-1.2.14.jar b/extensions/persist/lib/log4j-1.2.14.jar
new file mode 100644
index 0000000..6251307
--- /dev/null
+++ b/extensions/persist/lib/log4j-1.2.14.jar
Binary files differ
diff --git a/extensions/persist/lib/ognl-2.6.7.jar b/extensions/persist/lib/ognl-2.6.7.jar
new file mode 100644
index 0000000..cb9a666
--- /dev/null
+++ b/extensions/persist/lib/ognl-2.6.7.jar
Binary files differ
diff --git a/extensions/persist/lib/oro-2.0.8.jar b/extensions/persist/lib/oro-2.0.8.jar
new file mode 100644
index 0000000..23488d2
--- /dev/null
+++ b/extensions/persist/lib/oro-2.0.8.jar
Binary files differ
diff --git a/extensions/persist/lib/servlet-api-2.5.jar b/extensions/persist/lib/servlet-api-2.5.jar
new file mode 100644
index 0000000..fb52493
--- /dev/null
+++ b/extensions/persist/lib/servlet-api-2.5.jar
Binary files differ
diff --git a/extensions/persist/lib/xwork-2.0.4.jar b/extensions/persist/lib/xwork-2.0.4.jar
new file mode 100644
index 0000000..a7d763d
--- /dev/null
+++ b/extensions/persist/lib/xwork-2.0.4.jar
Binary files differ
diff --git a/extensions/persist/pom.xml b/extensions/persist/pom.xml
new file mode 100644
index 0000000..1eb12db
--- /dev/null
+++ b/extensions/persist/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-persist</artifactId>
+
+  <name>Google Guice - Extensions - Persist</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.hibernate.javax.persistence</groupId>
+      <artifactId>hibernate-jpa-2.0-api</artifactId>
+      <version>1.0.0.Final</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.5</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>1.6.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-entitymanager</artifactId>
+      <version>4.1.7.Final</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hsqldb</groupId>
+      <artifactId>hsqldb-j5</artifactId>
+      <version>2.0.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-library</artifactId>
+      <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-core</artifactId>
+      <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/extensions/persist/src/com/google/inject/persist/PersistFilter.java b/extensions/persist/src/com/google/inject/persist/PersistFilter.java
new file mode 100644
index 0000000..1aba144
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/PersistFilter.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (C) 2010 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.inject.persist;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * Apply this filter to enable the HTTP Request unit of work and to have
+ * guice-persist manage the lifecycle of active units of work.
+ * The filter automatically starts and stops the relevant {@link PersistService}
+ * upon {@link javax.servlet.Filter#init(javax.servlet.FilterConfig)} and
+ * {@link javax.servlet.Filter#destroy()} respectively.
+ *
+ * <p> To be able to use the open session-in-view pattern (i.e. work per request),
+ * register this filter <b>once</b> in your Guice {@code ServletModule}. It is
+ * important that you register this filter before any other filter.
+ *
+ * For multiple providers, you should register this filter once per provider, inside
+ * a private module for each persist module installed (this must be the same private
+ * module where the specific persist module is itself installed).
+ *
+ * <p>
+ * Example configuration:
+ * <pre>{@code
+ *  public class MyModule extends ServletModule {
+ *    public void configureServlets() {
+ *      filter("/*").through(PersistFilter.class);
+ *
+ *      serve("/index.html").with(MyHtmlServlet.class);
+ *      // Etc.
+ *    }
+ *  }
+ * }</pre>
+ * <p>
+ * This filter is thread safe and allows you to create injectors concurrently
+ * and deploy multiple guice-persist modules within the same injector, or even
+ * multiple injectors with persist modules withing the same JVM or web app.
+ * <p>
+ * This filter requires the Guice Servlet extension.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+@Singleton
+public final class PersistFilter implements Filter {
+  private final UnitOfWork unitOfWork;
+  private final PersistService persistService;
+
+  @Inject
+  public PersistFilter(UnitOfWork unitOfWork, PersistService persistService) {
+    this.unitOfWork = unitOfWork;
+    this.persistService = persistService;
+  }
+
+  public void init(FilterConfig filterConfig) throws ServletException {
+    persistService.start();
+  }
+
+  public void destroy() {
+    persistService.stop();
+  }
+
+  public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
+      final FilterChain filterChain) throws IOException, ServletException {
+
+    unitOfWork.begin();
+    try {
+      filterChain.doFilter(servletRequest, servletResponse);
+    } finally {
+      unitOfWork.end();
+    }
+  }
+}
diff --git a/extensions/persist/src/com/google/inject/persist/PersistModule.java b/extensions/persist/src/com/google/inject/persist/PersistModule.java
new file mode 100644
index 0000000..8efe895
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/PersistModule.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2010 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.inject.persist;
+
+import static com.google.inject.matcher.Matchers.annotatedWith;
+import static com.google.inject.matcher.Matchers.any;
+
+import com.google.inject.AbstractModule;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+/**
+ * Install this module to add guice-persist library support for JPA persistence
+ * providers.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public abstract class PersistModule extends AbstractModule {
+
+  @Override
+  protected final void configure() {
+    configurePersistence();
+
+    requireBinding(PersistService.class);
+    requireBinding(UnitOfWork.class);
+    /*if[AOP]*/
+    // wrapping in an if[AOP] just to allow this to compile in NO_AOP -- it won't be used
+    
+    // class-level @Transacational
+    bindInterceptor(annotatedWith(Transactional.class), any(), getTransactionInterceptor());
+    // method-level @Transacational
+    bindInterceptor(any(), annotatedWith(Transactional.class), getTransactionInterceptor());
+    /*end[AOP]*/
+  }
+
+  protected abstract void configurePersistence();
+
+  protected abstract MethodInterceptor getTransactionInterceptor();
+}
diff --git a/extensions/persist/src/com/google/inject/persist/PersistService.java b/extensions/persist/src/com/google/inject/persist/PersistService.java
new file mode 100644
index 0000000..85d4b35
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/PersistService.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2010 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.inject.persist;
+
+/**
+ * Persistence provider service. Use this to manage the overall
+ * startup and stop of the persistence module(s).
+ *
+ * TODO(dhanji): Integrate with Service API when appropriate.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public interface PersistService {
+
+  /**
+   * Starts the underlying persistence engine and makes guice-persist ready for
+   * use. For instance, with JPA, it creates an EntityManagerFactory and may
+   * open connection pools. This method must be called by your code prior to
+   * using any guice-persist or JPA artifacts. If already started,
+   * calling this method does nothing, if already stopped, it also does
+   * nothing.
+   */
+  void start();
+
+  /**
+   * Stops the underlying persistence engine. For instance, with JPA, it
+   * closes the {@code EntityManagerFactory}. If already stopped, calling this
+   * method does nothing. If not yet started, it also does nothing.
+   */
+  void stop();
+}
diff --git a/extensions/persist/src/com/google/inject/persist/Transactional.java b/extensions/persist/src/com/google/inject/persist/Transactional.java
new file mode 100644
index 0000000..9a8bbfb
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/Transactional.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2010 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.inject.persist;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p> Any method or class marked with this annotation will be considered for transactionality.
+ * Consult the documentation on https://github.com/google/guice/wiki/GuicePersist for detailed
+ * semantics.
+ * Marking a method {@code @Transactional} will start a new transaction before the method
+ * executes and commit it after the method returns.
+ * <p>
+ * If the method throws an exception, the transaction will be rolled back <em>unless</em>
+ * you have specifically requested not to in the {@link #ignore()} clause.
+ * <p>
+ * Similarly, the set of exceptions that will trigger a rollback can be defined in
+ * the {@link #rollbackOn()} clause. By default, only unchecked exceptions trigger a
+ * rollback.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface Transactional {
+
+  /**
+   * A list of exceptions to rollback on, if thrown by the transactional method.
+   * These exceptions are propagated correctly after a rollback.
+   */
+  Class<? extends Exception>[] rollbackOn() default RuntimeException.class;
+
+  /**
+   * A list of exceptions to <b>not<b> rollback on. A caveat to the rollbackOn clause.
+   * The disjunction of rollbackOn and ignore represents the list of exceptions
+   * that will trigger a rollback.
+   * The complement of rollbackOn and the universal set plus any exceptions in the
+   * ignore set represents the list of exceptions that will trigger a commit.
+   * Note that ignore exceptions take precedence over rollbackOn, but with subtype
+   * granularity.
+   */
+  Class<? extends Exception>[] ignore() default { };
+}
diff --git a/extensions/persist/src/com/google/inject/persist/UnitOfWork.java b/extensions/persist/src/com/google/inject/persist/UnitOfWork.java
new file mode 100644
index 0000000..061a6ab
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/UnitOfWork.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2010 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.inject.persist;
+
+/**
+ * This interface is used to gain manual control over the unit of work. This is mostly to do
+ * work in non-request, non-transactional threads. Or where more fine-grained control over the unit
+ * of work is required. Starting and ending a unit of work directly corresponds to opening and
+ * closing a {@code Session}, {@code EntityManager} or {@code ObjectContainer} respectively.
+ * <p> The
+ * Unit of Work referred to by UnitOfWork will always be local to the calling thread. Be careful to
+ * end() in a finally block. Neither JPA, nor Hibernate supports threadsafe sessions (reasoning
+ * behind thread-locality of Unit of Work semantics).
+ *
+ * <ul>
+ *   <li>Using UnitOfWork with the PersistFilter inside a request is not recommended.</li>
+ *   <li>Using UnitOfWork with session-per-txn strategy is not terribly clever either.</li>
+ *   <li>Using UnitOfWork with session-per-request strategy but *outside* a request (i.e. in a
+ *       background or bootstrap thread) is probably a good use case.</li>
+ *  </ul>
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail com)
+ */
+public interface UnitOfWork {
+
+  /**
+   * Starts a Unit Of Work. Underneath, causes a session to the data layer to be opened. If there
+   * is already one open, the invocation will do nothing. In this way, you can define arbitrary
+   * units-of-work that nest within one another safely.
+   *
+   * Transaction semantics are not affected.
+   */
+  void begin();
+
+  /**
+   * Declares an end to the current Unit of Work. Underneath, causes any open session to the data
+   * layer to close. If there is no Unit of work open, then the call returns silently. You can
+   * safely invoke end() repeatedly.
+   * <p>
+   * Transaction semantics are not affected.
+   */
+  void end();
+}
diff --git a/extensions/persist/src/com/google/inject/persist/finder/DynamicFinder.java b/extensions/persist/src/com/google/inject/persist/finder/DynamicFinder.java
new file mode 100644
index 0000000..3bcd931
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/finder/DynamicFinder.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.finder;
+
+import java.lang.reflect.Method;
+
+/**
+ * Utility that helps you introspect dynamic finder methods.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public final class DynamicFinder {
+  private final Method method;
+  private final Finder finder;
+
+  public DynamicFinder(Method method) {
+    this.method = method;
+    this.finder = method.getAnnotation(Finder.class);
+  }
+
+  /**
+   * Returns some metadata if the method is annotated {@code @Finder} or null.
+   *
+   * @param method a method you want to test as a dynamic finder
+   */
+  public static DynamicFinder from(Method method) {
+    return method.isAnnotationPresent(Finder.class) ? new DynamicFinder(method) : null;
+  }
+
+  public Finder metadata() {
+    return finder;
+  }
+}
diff --git a/extensions/persist/src/com/google/inject/persist/finder/Finder.java b/extensions/persist/src/com/google/inject/persist/finder/Finder.java
new file mode 100644
index 0000000..7bfbc92
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/finder/Finder.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.finder;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Collection;
+
+/**
+ * Marks a method stub as a dynamic finder. The method is intercepted and replaced with the
+ * specified JPAQL query. Provides result auto-boxing and automatic parameter binding.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Finder {
+  /**
+   * Returns the configured named query's name. Specify a named query's name
+   * here. This name is typically specified in your JPA configuration.
+   */
+  String namedQuery() default "";
+
+  /**
+   * Returns the configured query string. Directly specify a JPAQL query here.
+   */
+  String query() default "";
+
+  /**
+   * Returns the configured autoboxing collection class.
+   * Use this clause to specify a collection impl to autobox result lists into. The impl must
+   * have a default no-arg constructor and be a subclass of {@code java.util.Collection}.
+   */
+  Class<? extends Collection> returnAs() default Collection.class;
+}
\ No newline at end of file
diff --git a/extensions/persist/src/com/google/inject/persist/finder/FirstResult.java b/extensions/persist/src/com/google/inject/persist/finder/FirstResult.java
new file mode 100644
index 0000000..0feed7e
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/finder/FirstResult.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.finder;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotate any dynamic finder method's integer argument with this to pass in
+ * the index of the first result in the result set you are interested in.
+ * Useful for paging result sets. Complemented by {@link MaxResults}.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FirstResult {
+}
diff --git a/extensions/persist/src/com/google/inject/persist/finder/MaxResults.java b/extensions/persist/src/com/google/inject/persist/finder/MaxResults.java
new file mode 100644
index 0000000..69223d0
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/finder/MaxResults.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.finder;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotate any dynamic finder method's integer argument with this to pass in
+ * the maximum size of returned result window. Usefule for paging result sets.
+ * Complement of {@link FirstResult}.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MaxResults {
+}
diff --git a/extensions/persist/src/com/google/inject/persist/finder/package-info.java b/extensions/persist/src/com/google/inject/persist/finder/package-info.java
new file mode 100644
index 0000000..279929c
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/finder/package-info.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (C) 2010 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.
+ */
+
+/**
+ * Dynamic Finder API for Guice Persist.
+ */
+package com.google.inject.persist.finder;
diff --git a/extensions/persist/src/com/google/inject/persist/jpa/Jpa.java b/extensions/persist/src/com/google/inject/persist/jpa/Jpa.java
new file mode 100644
index 0000000..0e7ac27
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/jpa/Jpa.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A binding annotation for internal JPA module properties.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@BindingAnnotation @interface Jpa {}
diff --git a/extensions/persist/src/com/google/inject/persist/jpa/JpaFinderProxy.java b/extensions/persist/src/com/google/inject/persist/jpa/JpaFinderProxy.java
new file mode 100644
index 0000000..774fa9f
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/jpa/JpaFinderProxy.java
@@ -0,0 +1,279 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.common.collect.MapMaker;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import com.google.inject.persist.finder.Finder;
+import com.google.inject.persist.finder.FirstResult;
+import com.google.inject.persist.finder.MaxResults;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+/**
+ * TODO(dhanji): Make this work!!
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+@Singleton
+class JpaFinderProxy implements MethodInterceptor {
+  private final Map<Method, FinderDescriptor> finderCache = new MapMaker().weakKeys().makeMap();
+  private final Provider<EntityManager> emProvider;
+
+  @Inject
+  public JpaFinderProxy(Provider<EntityManager> emProvider) {
+    this.emProvider = emProvider;
+  }
+
+  public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+    EntityManager em = emProvider.get();
+
+    //obtain a cached finder descriptor (or create a new one)
+    JpaFinderProxy.FinderDescriptor finderDescriptor = getFinderDescriptor(methodInvocation);
+
+    Object result = null;
+
+    //execute as query (named params or otherwise)
+    Query jpaQuery = finderDescriptor.createQuery(em);
+    if (finderDescriptor.isBindAsRawParameters) {
+      bindQueryRawParameters(jpaQuery, finderDescriptor, methodInvocation.getArguments());
+    } else {
+      bindQueryNamedParameters(jpaQuery, finderDescriptor, methodInvocation.getArguments());
+    }
+
+    //depending upon return type, decorate or return the result as is
+    if (JpaFinderProxy.ReturnType.PLAIN.equals(finderDescriptor.returnType)) {
+      result = jpaQuery.getSingleResult();
+    } else if (JpaFinderProxy.ReturnType.COLLECTION.equals(finderDescriptor.returnType)) {
+      result = getAsCollection(finderDescriptor, jpaQuery.getResultList());
+    } else if (JpaFinderProxy.ReturnType.ARRAY.equals(finderDescriptor.returnType)) {
+      result = jpaQuery.getResultList().toArray();
+    }
+
+    return result;
+  }
+
+  private Object getAsCollection(JpaFinderProxy.FinderDescriptor finderDescriptor,
+      List results) {
+    Collection<?> collection;
+    try {
+      collection = (Collection) finderDescriptor.returnCollectionTypeConstructor.newInstance();
+    } catch (InstantiationException e) {
+      throw new RuntimeException(
+          "Specified collection class of Finder's returnAs could not be instantated: "
+              + finderDescriptor.returnCollectionType, e);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(
+          "Specified collection class of Finder's returnAs could not be instantated (do not have access privileges): "
+              + finderDescriptor.returnCollectionType, e);
+    } catch (InvocationTargetException e) {
+      throw new RuntimeException(
+          "Specified collection class of Finder's returnAs could not be instantated (it threw an exception): "
+              + finderDescriptor.returnCollectionType, e);
+    }
+
+    collection.addAll(results);
+    return collection;
+  }
+
+  private void bindQueryNamedParameters(Query jpaQuery,
+      JpaFinderProxy.FinderDescriptor descriptor, Object[] arguments) {
+    for (int i = 0; i < arguments.length; i++) {
+      Object argument = arguments[i];
+      Object annotation = descriptor.parameterAnnotations[i];
+
+      if (null == annotation)
+      //noinspection UnnecessaryContinue
+      {
+        continue;   //skip param as it's not bindable
+      } else if (annotation instanceof Named) {
+        Named named = (Named) annotation;
+        jpaQuery.setParameter(named.value(), argument);
+      } else if (annotation instanceof javax.inject.Named) {
+        javax.inject.Named named = (javax.inject.Named) annotation;
+        jpaQuery.setParameter(named.value(), argument);
+      } else if (annotation instanceof FirstResult) {
+        jpaQuery.setFirstResult((Integer) argument);
+      } else if (annotation instanceof MaxResults) {
+        jpaQuery.setMaxResults((Integer) argument);
+      }
+    }
+  }
+
+  private void bindQueryRawParameters(Query jpaQuery,
+      JpaFinderProxy.FinderDescriptor descriptor, Object[] arguments) {
+    for (int i = 0, index = 1; i < arguments.length; i++) {
+      Object argument = arguments[i];
+      Object annotation = descriptor.parameterAnnotations[i];
+
+      if (null == annotation) {
+        //bind it as a raw param (1-based index, yes I know its different from Hibernate, blargh)
+        jpaQuery.setParameter(index, argument);
+        index++;
+      } else if (annotation instanceof FirstResult) {
+        jpaQuery.setFirstResult((Integer) argument);
+      } else if (annotation instanceof MaxResults) {
+        jpaQuery.setMaxResults((Integer) argument);
+      }
+    }
+  }
+
+  private JpaFinderProxy.FinderDescriptor getFinderDescriptor(MethodInvocation invocation) {
+    Method method = invocation.getMethod();
+    JpaFinderProxy.FinderDescriptor finderDescriptor = finderCache.get(method);
+    if (null != finderDescriptor) {
+      return finderDescriptor;
+    }
+
+    //otherwise reflect and cache finder info...
+    finderDescriptor = new JpaFinderProxy.FinderDescriptor();
+
+    //determine return type
+    finderDescriptor.returnClass = invocation.getMethod().getReturnType();
+    finderDescriptor.returnType = determineReturnType(finderDescriptor.returnClass);
+
+    //determine finder query characteristics
+    Finder finder = invocation.getMethod().getAnnotation(Finder.class);
+    String query = finder.query();
+    if (!"".equals(query.trim())) {
+      finderDescriptor.setQuery(query);
+    } else {
+      finderDescriptor.setNamedQuery(finder.namedQuery());
+    }
+
+    //determine parameter annotations
+    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+    Object[] discoveredAnnotations = new Object[parameterAnnotations.length];
+    for (int i = 0; i < parameterAnnotations.length; i++) {
+      Annotation[] annotations = parameterAnnotations[i];
+      //each annotation per param
+      for (Annotation annotation : annotations) {
+        //discover the named, first or max annotations then break out
+        Class<? extends Annotation> annotationType = annotation.annotationType();
+        if (Named.class.equals(annotationType) || javax.inject.Named.class.equals(annotationType)) {
+          discoveredAnnotations[i] = annotation;
+          finderDescriptor.isBindAsRawParameters = false;
+          break;
+        } else if (FirstResult.class.equals(annotationType)) {
+          discoveredAnnotations[i] = annotation;
+          break;
+        } else if (MaxResults.class.equals(annotationType)) {
+          discoveredAnnotations[i] = annotation;
+          break;
+        }   //leave as null for no binding
+      }
+    }
+
+    //set the discovered set to our finder cache object
+    finderDescriptor.parameterAnnotations = discoveredAnnotations;
+
+    //discover the returned collection implementation if this finder returns a collection
+    if (JpaFinderProxy.ReturnType.COLLECTION.equals(finderDescriptor.returnType)
+        && finderDescriptor.returnClass != Collection.class) {
+      finderDescriptor.returnCollectionType = finder.returnAs();
+      try {
+        finderDescriptor.returnCollectionTypeConstructor = finderDescriptor.returnCollectionType
+            .getConstructor();
+        finderDescriptor.returnCollectionTypeConstructor.setAccessible(true);   //UGH!
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException(
+            "Finder's collection return type specified has no default constructor! returnAs: "
+                + finderDescriptor.returnCollectionType, e);
+      }
+    }
+
+    //cache it
+    cacheFinderDescriptor(method, finderDescriptor);
+
+    return finderDescriptor;
+  }
+
+  /**
+   * writes to a chm (used to provide copy-on-write but this is bettah!)
+   *
+   * @param method The key
+   * @param finderDescriptor The descriptor to cache
+   */
+  private void cacheFinderDescriptor(Method method, FinderDescriptor finderDescriptor) {
+    //write to concurrent map
+    finderCache.put(method, finderDescriptor);
+  }
+
+  private JpaFinderProxy.ReturnType determineReturnType(Class<?> returnClass) {
+    if (Collection.class.isAssignableFrom(returnClass)) {
+      return JpaFinderProxy.ReturnType.COLLECTION;
+    } else if (returnClass.isArray()) {
+      return JpaFinderProxy.ReturnType.ARRAY;
+    }
+
+    return JpaFinderProxy.ReturnType.PLAIN;
+  }
+
+  /**
+   * A wrapper data class that caches information about a finder method.
+   */
+  private static class FinderDescriptor {
+    private volatile boolean isKeyedQuery = false;
+    volatile boolean isBindAsRawParameters = true;
+        //should we treat the query as having ? instead of :named params
+    volatile JpaFinderProxy.ReturnType returnType;
+    volatile Class<?> returnClass;
+    volatile Class<? extends Collection> returnCollectionType;
+    volatile Constructor returnCollectionTypeConstructor;
+    volatile Object[] parameterAnnotations;
+        //contract is: null = no bind, @Named = param, @FirstResult/@MaxResults for paging
+
+    private String query;
+    private String name;
+
+    void setQuery(String query) {
+      this.query = query;
+    }
+
+    void setNamedQuery(String name) {
+      this.name = name;
+      isKeyedQuery = true;
+    }
+
+    public boolean isKeyedQuery() {
+      return isKeyedQuery;
+    }
+
+    Query createQuery(EntityManager em) {
+      return isKeyedQuery ? em.createNamedQuery(name) : em.createQuery(query);
+    }
+  }
+
+  private static enum ReturnType {
+    PLAIN, COLLECTION, ARRAY
+  }
+}
diff --git a/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java b/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java
new file mode 100644
index 0000000..1f59a6d
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java
@@ -0,0 +1,163 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Inject;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.Method;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+class JpaLocalTxnInterceptor implements MethodInterceptor {
+
+  // TODO(gak): Move these args to the cxtor & make these final.
+  @Inject
+  private JpaPersistService emProvider = null;
+
+  @Inject
+  private UnitOfWork unitOfWork = null;
+
+  @Transactional
+  private static class Internal {}
+
+  // Tracks if the unit of work was begun implicitly by this transaction.
+  private final ThreadLocal<Boolean> didWeStartWork = new ThreadLocal<Boolean>();
+
+  public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+
+    // Should we start a unit of work?
+    if (!emProvider.isWorking()) {
+      emProvider.begin();
+      didWeStartWork.set(true);
+    }
+
+    Transactional transactional = readTransactionMetadata(methodInvocation);
+    EntityManager em = this.emProvider.get();
+
+    // Allow 'joining' of transactions if there is an enclosing @Transactional method.
+    if (em.getTransaction().isActive()) {
+      return methodInvocation.proceed();
+    }
+
+    final EntityTransaction txn = em.getTransaction();
+    txn.begin();
+
+    Object result;
+    try {
+      result = methodInvocation.proceed();
+
+    } catch (Exception e) {
+      //commit transaction only if rollback didnt occur
+      if (rollbackIfNecessary(transactional, e, txn)) {
+        txn.commit();
+      }
+
+      //propagate whatever exception is thrown anyway
+      throw e;
+    } finally {
+      // Close the em if necessary (guarded so this code doesn't run unless catch fired).
+      if (null != didWeStartWork.get() && !txn.isActive()) {
+        didWeStartWork.remove();
+        unitOfWork.end();
+      }
+    }
+
+    //everything was normal so commit the txn (do not move into try block above as it
+    //  interferes with the advised method's throwing semantics)
+    try {
+      txn.commit();
+    } finally {
+      //close the em if necessary
+      if (null != didWeStartWork.get() ) {
+        didWeStartWork.remove();
+        unitOfWork.end();
+      }
+    }
+
+    //or return result
+    return result;
+  }
+
+  // TODO(dhanji): Cache this method's results.
+  private Transactional readTransactionMetadata(MethodInvocation methodInvocation) {
+    Transactional transactional;
+    Method method = methodInvocation.getMethod();
+    Class<?> targetClass = methodInvocation.getThis().getClass();
+
+    transactional = method.getAnnotation(Transactional.class);
+    if (null == transactional) {
+      // If none on method, try the class.
+      transactional = targetClass.getAnnotation(Transactional.class);
+    }
+    if (null == transactional) {
+      // If there is no transactional annotation present, use the default
+      transactional = Internal.class.getAnnotation(Transactional.class);
+    }
+
+    return transactional;
+  }
+
+  /**
+   * Returns True if rollback DID NOT HAPPEN (i.e. if commit should continue).
+   *
+   * @param transactional The metadata annotaiton of the method
+   * @param e The exception to test for rollback
+   * @param txn A JPA Transaction to issue rollbacks on
+   */
+  private boolean rollbackIfNecessary(Transactional transactional, Exception e,
+      EntityTransaction txn) {
+    boolean commit = true;
+
+    //check rollback clauses
+    for (Class<? extends Exception> rollBackOn : transactional.rollbackOn()) {
+
+      //if one matched, try to perform a rollback
+      if (rollBackOn.isInstance(e)) {
+        commit = false;
+
+        //check ignore clauses (supercedes rollback clause)
+        for (Class<? extends Exception> exceptOn : transactional.ignore()) {
+          //An exception to the rollback clause was found, DON'T rollback
+          // (i.e. commit and throw anyway)
+          if (exceptOn.isInstance(e)) {
+            commit = true;
+            break;
+          }
+        }
+
+        //rollback only if nothing matched the ignore check
+        if (!commit) {
+          txn.rollback();
+        }
+        //otherwise continue to commit
+
+        break;
+      }
+    }
+
+    return commit;
+  }
+}
diff --git a/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistModule.java b/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistModule.java
new file mode 100644
index 0000000..e9996c0
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistModule.java
@@ -0,0 +1,182 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+import com.google.inject.TypeLiteral;
+import com.google.inject.persist.PersistModule;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.UnitOfWork;
+import com.google.inject.persist.finder.DynamicFinder;
+import com.google.inject.persist.finder.Finder;
+import com.google.inject.util.Providers;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+/**
+ * JPA provider for guice persist.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public final class JpaPersistModule extends PersistModule {
+  private final String jpaUnit;
+
+  public JpaPersistModule(String jpaUnit) {
+    Preconditions.checkArgument(null != jpaUnit && jpaUnit.length() > 0,
+        "JPA unit name must be a non-empty string.");
+    this.jpaUnit = jpaUnit;
+  }
+
+  private Map<?,?> properties;
+  private MethodInterceptor transactionInterceptor;
+
+  @Override protected void configurePersistence() {
+    bindConstant().annotatedWith(Jpa.class).to(jpaUnit);
+
+    bind(JpaPersistService.class).in(Singleton.class);
+
+    bind(PersistService.class).to(JpaPersistService.class);
+    bind(UnitOfWork.class).to(JpaPersistService.class);
+    bind(EntityManager.class).toProvider(JpaPersistService.class);
+    bind(EntityManagerFactory.class)
+        .toProvider(JpaPersistService.EntityManagerFactoryProvider.class);
+
+    transactionInterceptor = new JpaLocalTxnInterceptor();
+    requestInjection(transactionInterceptor);
+
+    // Bind dynamic finders.
+    for (Class<?> finder : dynamicFinders) {
+      bindFinder(finder);
+    }
+  }
+
+  @Override protected MethodInterceptor getTransactionInterceptor() {
+    return transactionInterceptor;
+  }
+
+  @Provides @Jpa Map<?, ?> provideProperties() {
+    return properties;
+  }
+
+  /**
+   * Configures the JPA persistence provider with a set of properties.
+   * 
+   * @param properties A set of name value pairs that configure a JPA persistence
+   *     provider as per the specification.
+   * @since 4.0 (since 3.0 with a parameter type of {@code java.util.Properties})
+   */
+  public JpaPersistModule properties(Map<?,?> properties) {
+    this.properties = properties;
+    return this;
+  }
+
+  private final List<Class<?>> dynamicFinders = Lists.newArrayList();
+
+  /**
+   * Adds an interface to this module to use as a dynamic finder.
+   *
+   * @param iface Any interface type whose methods are all dynamic finders.
+   */
+  public <T> JpaPersistModule addFinder(Class<T> iface) {
+    dynamicFinders.add(iface);
+    return this;
+  }
+
+  private <T> void bindFinder(Class<T> iface) {
+    if (!isDynamicFinderValid(iface)) {
+      return;
+    }
+
+    InvocationHandler finderInvoker = new InvocationHandler() {
+      @Inject JpaFinderProxy finderProxy;
+
+      public Object invoke(final Object thisObject, final Method method, final Object[] args)
+          throws Throwable {
+
+        // Don't intercept non-finder methods like equals and hashcode.
+        if (!method.isAnnotationPresent(Finder.class)) {
+          // NOTE(dhanji): This is not ideal, we are using the invocation handler's equals
+          // and hashcode as a proxy (!) for the proxy's equals and hashcode. 
+          return method.invoke(this, args);
+        }
+
+        return finderProxy.invoke(new MethodInvocation() {
+          public Method getMethod() {
+            return method;
+          }
+
+          public Object[] getArguments() {
+            return null == args ? new Object[0] : args; 
+          }
+
+          public Object proceed() throws Throwable {
+            return method.invoke(thisObject, args);
+          }
+
+          public Object getThis() {
+            throw new UnsupportedOperationException("Bottomless proxies don't expose a this.");
+          }
+
+          public AccessibleObject getStaticPart() {
+            throw new UnsupportedOperationException();
+          }
+        });
+      }
+    };
+    requestInjection(finderInvoker);
+
+    @SuppressWarnings("unchecked") // Proxy must produce instance of type given.
+    T proxy = (T) Proxy
+        .newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { iface },
+            finderInvoker);
+
+    bind(iface).toInstance(proxy);
+  }
+
+  private boolean isDynamicFinderValid(Class<?> iface) {
+    boolean valid = true;
+    if (!iface.isInterface()) {
+      addError(iface + " is not an interface. Dynamic Finders must be interfaces.");
+      valid = false;
+    }
+
+    for (Method method : iface.getMethods()) {
+      DynamicFinder finder = DynamicFinder.from(method);
+      if (null == finder) {
+        addError("Dynamic Finder methods must be annotated with @Finder, but " + iface
+            + "." + method.getName() + " was not");
+        valid = false;
+      }
+    }
+    return valid;
+  }
+}
diff --git a/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistService.java b/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistService.java
new file mode 100644
index 0000000..190506c
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistService.java
@@ -0,0 +1,139 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.UnitOfWork;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+@Singleton
+class JpaPersistService implements Provider<EntityManager>, UnitOfWork, PersistService {
+  private final ThreadLocal<EntityManager> entityManager = new ThreadLocal<EntityManager>();
+
+  private final String persistenceUnitName;
+  private final Map<?,?> persistenceProperties;
+
+  @Inject
+  public JpaPersistService(@Jpa String persistenceUnitName,
+      @Nullable @Jpa Map<?,?> persistenceProperties) {
+    this.persistenceUnitName = persistenceUnitName;
+    this.persistenceProperties = persistenceProperties;
+  }
+
+  public EntityManager get() {
+    if (!isWorking()) {
+      begin();
+    }
+
+    EntityManager em = entityManager.get();
+    Preconditions.checkState(null != em, "Requested EntityManager outside work unit. "
+        + "Try calling UnitOfWork.begin() first, or use a PersistFilter if you "
+        + "are inside a servlet environment.");
+
+    return em;
+  }
+
+  public boolean isWorking() {
+    return entityManager.get() != null;
+  }
+
+  public void begin() {
+    Preconditions.checkState(null == entityManager.get(),
+        "Work already begun on this thread. Looks like you have called UnitOfWork.begin() twice"
+         + " without a balancing call to end() in between.");
+
+    entityManager.set(emFactory.createEntityManager());
+  }
+
+  public void end() {
+    EntityManager em = entityManager.get();
+
+    // Let's not penalize users for calling end() multiple times.
+    if (null == em) {
+      return;
+    }
+
+    try {
+      em.close();
+    }
+    finally {
+      entityManager.remove();
+    }
+  }
+
+  private volatile EntityManagerFactory emFactory;
+
+  @VisibleForTesting
+  synchronized void start(EntityManagerFactory emFactory) {
+    this.emFactory = emFactory;
+  }
+
+  public synchronized void start() {
+    Preconditions.checkState(null == emFactory, "Persistence service was already initialized.");
+
+    if (null != persistenceProperties) {
+      this.emFactory = Persistence
+          .createEntityManagerFactory(persistenceUnitName, persistenceProperties);
+    } else {
+      this.emFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
+    }
+  }
+
+  public synchronized void stop() {
+    Preconditions.checkState(emFactory.isOpen(), "Persistence service was already shut down.");
+    emFactory.close();
+  }
+
+  @Singleton
+  public static class EntityManagerFactoryProvider implements Provider<EntityManagerFactory> {
+    private final JpaPersistService emProvider;
+
+    @Inject
+    public EntityManagerFactoryProvider(JpaPersistService emProvider) {
+      this.emProvider = emProvider;
+    }
+
+    public EntityManagerFactory get() {
+      assert null != emProvider.emFactory;
+      return emProvider.emFactory;
+    }
+  }
+  
+  @Documented
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target(ElementType.PARAMETER)
+  private @interface Nullable { }
+
+}
diff --git a/extensions/persist/src/com/google/inject/persist/jpa/package-info.java b/extensions/persist/src/com/google/inject/persist/jpa/package-info.java
new file mode 100644
index 0000000..f9e46da
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/jpa/package-info.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (C) 2010 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.
+ */
+
+/**
+ * guice-persist's Java Persistence API (JPA) support.
+ */
+package com.google.inject.persist.jpa;
diff --git a/extensions/persist/src/com/google/inject/persist/package-info.java b/extensions/persist/src/com/google/inject/persist/package-info.java
new file mode 100644
index 0000000..ed15e84
--- /dev/null
+++ b/extensions/persist/src/com/google/inject/persist/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/**
+ * Guice Persist: a lightweight persistence library for Guice; this extension requires {@code
+ * guice-persist.jar}.
+ */
+package com.google.inject.persist;
diff --git a/extensions/persist/test/META-INF/persistence.xml b/extensions/persist/test/META-INF/persistence.xml
new file mode 100644
index 0000000..881c7fd
--- /dev/null
+++ b/extensions/persist/test/META-INF/persistence.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
+        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
+
+    <!-- JPA test "unit" -->
+    <persistence-unit name="testUnit" transaction-type="RESOURCE_LOCAL">
+		<provider>org.hibernate.ejb.HibernatePersistence</provider>
+        
+        <class>com.google.inject.persist.jpa.JpaTestEntity</class>
+        <class>com.google.inject.persist.jpa.JpaParentTestEntity</class>
+        <exclude-unlisted-classes>true</exclude-unlisted-classes>
+
+        <properties>
+            <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
+            <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:persistence"/>
+            <property name="hibernate.connection.username" value="sa"/>
+            <property name="hibernate.connection.password" value=""/>
+            <property name="hibernate.connection.pool_size" value="2"/>
+            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
+            <property name="hiberante.cache_provider" value="org.hibernate.cache.NoCacheProvider"/>
+
+            <property name="hibernate.hbm2ddl.auto" value="create"/>
+        </properties>
+    </persistence-unit>
+
+    <persistence-unit name="testProperties" transaction-type="RESOURCE_LOCAL">
+        <provider>org.hibernate.ejb.HibernatePersistence</provider>
+
+        <class>com.google.inject.persist.jpa.JpaTestEntity</class>
+        <class>com.google.inject.persist.jpa.JpaParentTestEntity</class>
+        <exclude-unlisted-classes>true</exclude-unlisted-classes>
+
+        <properties>
+            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
+            <property name="hibernate.id.new_generator_mappings" value="true"/>
+            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
+        </properties>
+    </persistence-unit>
+
+</persistence>
+
diff --git a/extensions/persist/test/com/google/inject/persist/AllTests.java b/extensions/persist/test/com/google/inject/persist/AllTests.java
new file mode 100644
index 0000000..8651fc6
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/AllTests.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2010 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.inject.persist;
+
+import com.google.inject.persist.jpa.ClassLevelManagedLocalTransactionsTest;
+import com.google.inject.persist.jpa.CustomPropsEntityManagerFactoryProvisionTest;
+import com.google.inject.persist.jpa.EntityManagerFactoryProvisionTest;
+import com.google.inject.persist.jpa.EntityManagerPerRequestProvisionTest;
+import com.google.inject.persist.jpa.EntityManagerProvisionTest;
+import com.google.inject.persist.jpa.JoiningLocalTransactionsTest;
+import com.google.inject.persist.jpa.JpaWorkManagerTest;
+import com.google.inject.persist.jpa.ManagedLocalTransactionsAcrossRequestTest;
+import com.google.inject.persist.jpa.ManagedLocalTransactionsTest;
+import com.google.inject.persist.jpa.ManualLocalTransactionsTest;
+import com.google.inject.persist.jpa.ManualLocalTransactionsWithCustomMatcherTest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class AllTests {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+
+    suite.addTestSuite(EdslTest.class);
+    suite.addTestSuite(ClassLevelManagedLocalTransactionsTest.class);
+    suite.addTestSuite(CustomPropsEntityManagerFactoryProvisionTest.class);
+    suite.addTestSuite(EntityManagerFactoryProvisionTest.class);
+    suite.addTestSuite(EntityManagerPerRequestProvisionTest.class);
+    suite.addTestSuite(EntityManagerProvisionTest.class);
+    suite.addTestSuite(JoiningLocalTransactionsTest.class);
+    suite.addTestSuite(JpaWorkManagerTest.class);
+    suite.addTestSuite(ManagedLocalTransactionsAcrossRequestTest.class);
+    suite.addTestSuite(ManagedLocalTransactionsTest.class);
+    suite.addTestSuite(ManualLocalTransactionsTest.class);
+    suite.addTestSuite(ManualLocalTransactionsWithCustomMatcherTest.class);
+
+    return suite;
+  }
+}
\ No newline at end of file
diff --git a/extensions/persist/test/com/google/inject/persist/EdslTest.java b/extensions/persist/test/com/google/inject/persist/EdslTest.java
new file mode 100644
index 0000000..81e0b6b
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/EdslTest.java
@@ -0,0 +1,26 @@
+package com.google.inject.persist;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Stage;
+import com.google.inject.persist.jpa.JpaPersistModule;
+import java.util.logging.Logger;
+import junit.framework.TestCase;
+
+/**
+ * @author dhanji@google.com (Dhanji R. Prasanna)
+ */
+public class EdslTest extends TestCase {
+
+  public void testModuleConfigUsingJpa() throws Exception {
+    Logger.getLogger(getClass().getName()).info("Starting EDSL test.");
+    Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new JpaPersistModule("myunit"));
+        binder().requireExplicitBindings();
+      }
+    });
+    Logger.getLogger(getClass().getName()).info("Completed EDSL test.");
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTest.java b/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTest.java
new file mode 100644
index 0000000..36fcb31
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTest.java
@@ -0,0 +1,204 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+
+import junit.framework.TestCase;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+/**
+ * This test asserts class level @Transactional annotation behavior.
+ *
+ * Class-level @Transactional is a shortcut if all non-private methods in the class are meant to be
+ * transactional.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class ClassLevelManagedLocalTransactionsTest extends TestCase {
+  private Injector injector;
+  private static final String UNIQUE_TEXT = "JPAsome unique text88888" + new Date();
+  private static final String UNIQUE_TEXT_2 = "JPAsome asda unique teasdalsdplasdxt" + new Date();
+  private static final String TRANSIENT_UNIQUE_TEXT = "JPAsome other unique texaksoksojadasdt"
+      + new Date();
+
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  public void tearDown() {
+    injector.getInstance(PersistService.class).stop();
+    injector = null;
+  }
+
+  public void testSimpleTransaction() {
+    injector.getInstance(TransactionalObject.class).runOperationInTxn();
+
+    EntityManager session = injector.getInstance(EntityManager.class);
+    assertFalse("EntityManager was not closed by transactional service",
+        session.getTransaction().isActive());
+
+    //test that the data has been stored
+    session.getTransaction().begin();
+    Object result = session.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT).getSingleResult();
+
+    session.getTransaction().commit();
+
+    assertTrue("odd result returned fatal", result instanceof JpaTestEntity);
+
+    assertEquals("queried entity did not match--did automatic txn fail?",
+        UNIQUE_TEXT, (((JpaTestEntity) result).getText()));
+  }
+
+  public void testSimpleTransactionRollbackOnChecked() {
+    try {
+      injector.getInstance(TransactionalObject2.class).runOperationInTxnThrowingChecked();
+    } catch (IOException e) {
+      //ignore
+    }
+
+    EntityManager session = injector.getInstance(EntityManager.class);
+    assertFalse("EntityManager was not closed by transactional service (rollback didnt happen?)",
+        session.getTransaction().isActive());
+
+    //test that the data has been stored
+    session.getTransaction().begin();
+    List<?> result = session.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", TRANSIENT_UNIQUE_TEXT).getResultList();
+
+    session.getTransaction().commit();
+
+    assertTrue("a result was returned! rollback sure didnt happen!!!", result.isEmpty());
+  }
+
+  public void testSimpleTransactionRollbackOnCheckedExcepting() {
+    Exception ex = null;
+    try {
+      injector.getInstance(TransactionalObject3.class).runOperationInTxnThrowingCheckedExcepting();
+      fail("Exception was not thrown by test txn-al method!");
+    } catch (IOException e) {
+      //ignored
+    }
+
+    EntityManager session = injector.getInstance(EntityManager.class);
+    assertFalse("Txn was not closed by transactional service (commit didnt happen?)",
+        session.getTransaction().isActive());
+
+    //test that the data has been stored
+    session.getTransaction().begin();
+    Object result = session.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT_2).getSingleResult();
+
+    session.getTransaction().commit();
+
+    assertNotNull("a result was not returned! rollback happened anyway (ignore failed)!!!",
+        result);
+  }
+
+  public void testSimpleTransactionRollbackOnUnchecked() {
+    try {
+      injector.getInstance(TransactionalObject4.class).runOperationInTxnThrowingUnchecked();
+    } catch (RuntimeException re) {
+      //ignore
+    }
+
+    EntityManager session = injector.getInstance(EntityManager.class);
+    assertFalse("EntityManager was not closed by transactional service (rollback didnt happen?)",
+        session.getTransaction().isActive());
+
+    //test that the data has been stored
+    session.getTransaction().begin();
+    List<?> result = session.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", TRANSIENT_UNIQUE_TEXT).getResultList();
+
+    session.getTransaction().commit();
+
+    assertTrue("a result was returned! rollback sure didnt happen!!!",
+        result.isEmpty());
+  }
+
+  @Transactional
+  public static class TransactionalObject {
+    @Inject EntityManager session;
+
+    public void runOperationInTxn() {
+      assertTrue(session.getTransaction().isActive());
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT);
+      session.persist(entity);
+    }
+
+  }
+
+  @Transactional
+  public static class TransactionalObject4 {
+    @Inject EntityManager session;
+
+    @Transactional
+    public void runOperationInTxnThrowingUnchecked() {
+      assertTrue(session.getTransaction().isActive());
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(TRANSIENT_UNIQUE_TEXT);
+      session.persist(entity);
+
+      throw new IllegalStateException();
+    }
+  }
+
+  @Transactional(rollbackOn = IOException.class, ignore = FileNotFoundException.class)
+  public static class TransactionalObject3 {
+    @Inject EntityManager session;
+
+    public void runOperationInTxnThrowingCheckedExcepting() throws IOException {
+      assertTrue(session.getTransaction().isActive());
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT_2);
+      session.persist(entity);
+
+      throw new FileNotFoundException();
+    }
+  }
+
+  @Transactional(rollbackOn = IOException.class)
+  public static class TransactionalObject2 {
+    @Inject EntityManager session;
+
+    public void runOperationInTxnThrowingChecked() throws IOException {
+      assertTrue(session.getTransaction().isActive());
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(TRANSIENT_UNIQUE_TEXT);
+      session.persist(entity);
+
+      throw new IOException();
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvisionTest.java b/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvisionTest.java
new file mode 100644
index 0000000..288b277
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvisionTest.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+
+import java.util.Properties;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class CustomPropsEntityManagerFactoryProvisionTest extends TestCase {
+  private Injector injector;
+
+  @Override
+  public void setUp() {
+    Properties props = new Properties();
+    props.put("blah", "blah");
+
+    injector = Guice.createInjector(new JpaPersistModule("testUnit").properties(props));
+  }
+
+  @Override
+  public final void tearDown() {
+    injector.getInstance(UnitOfWork.class).end();
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testSessionCreateOnInjection() {
+
+    assertEquals("SINGLETON VIOLATION " + UnitOfWork.class.getName(),
+        injector.getInstance(UnitOfWork.class),
+        injector.getInstance(UnitOfWork.class));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+
+    //obtain em
+    assertTrue(injector.getInstance(EntityManager.class).isOpen());
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/DynamicFinderTest.java b/extensions/persist/test/com/google/inject/persist/jpa/DynamicFinderTest.java
new file mode 100644
index 0000000..825d244
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/DynamicFinderTest.java
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.finder.Finder;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import javax.persistence.EntityManager;
+
+/**
+ * A test around providing sessions (starting, closing etc.)
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class DynamicFinderTest extends TestCase {
+  private Injector injector;
+
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit").addFinder(JpaFinder.class));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  public final void tearDown() {
+    injector.getInstance(PersistService.class).stop();
+  }
+
+  public void testDynamicFinderListAll() {
+    //obtain em
+    JpaDao dao = injector.getInstance(JpaDao.class);
+
+    //obtain same em again (bound to txn)
+    JpaTestEntity te = new JpaTestEntity();
+    te.setText("HIAjsOKAOSD" + new Date() + UUID.randomUUID());
+
+    dao.persist(te);
+
+    //im not sure this hack works...
+    assertFalse("Duplicate entity managers crossing-scope",
+        dao.lastEm.equals(injector.getInstance(EntityManager.class)));
+
+    List<JpaTestEntity> list = injector.getInstance(JpaFinder.class).listAll();
+    assertNotNull(list);
+    assertFalse(list.isEmpty());
+    assertEquals(1, list.size());
+    assertEquals(te, list.get(0));
+  }
+
+  public static interface JpaFinder {
+    @Finder(query = "from JpaTestEntity", returnAs = ArrayList.class)
+    public List<JpaTestEntity> listAll();
+  }
+
+  public static class JpaDao {
+    private final Provider<EntityManager> em;
+    EntityManager lastEm;
+
+    @Inject
+    public JpaDao(Provider<EntityManager> em) {
+     this.em = em;
+    }
+
+    @Transactional
+    public <T> void persist(T t) {
+      lastEm = em.get();
+      assertTrue("em is not open!", lastEm.isOpen());
+      assertTrue("no active txn!", lastEm.getTransaction().isActive());
+      lastEm.persist(t);
+
+      assertTrue("Persisting object failed", lastEm.contains(t));
+    }
+
+    @Transactional
+    public <T> boolean contains(T t) {
+      if (null == lastEm) {
+        lastEm = em.get();
+      }
+      return lastEm.contains(t);
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/EnsureJpaCanTakeObjectsInPropertiesTest.java b/extensions/persist/test/com/google/inject/persist/jpa/EnsureJpaCanTakeObjectsInPropertiesTest.java
new file mode 100644
index 0000000..6dcd6bd
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/EnsureJpaCanTakeObjectsInPropertiesTest.java
@@ -0,0 +1,110 @@
+/**
+ * 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.inject.persist.jpa;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+
+import org.hibernate.cfg.Environment;
+import org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider;
+import org.hsqldb.jdbc.JDBCDataSource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceException;
+import javax.sql.DataSource;
+
+public class EnsureJpaCanTakeObjectsInPropertiesTest extends TestCase {
+
+  private Injector injector;
+
+  public static class DBModule extends AbstractModule {
+
+    final DataSource ds;
+    final boolean passDataSource;
+
+    DBModule(DataSource ds, boolean passDataSource) {
+      this.ds = ds;
+      this.passDataSource = passDataSource;
+    }
+
+    @Override
+    protected void configure() {
+      Map<String, Object> p = new HashMap<String, Object>();
+
+      p.put(Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName());
+      if (passDataSource) {
+        p.put(Environment.DATASOURCE, ds);
+      }
+
+      JpaPersistModule jpaPersistModule = new JpaPersistModule("testProperties").properties(p);
+
+      install(jpaPersistModule);
+    }
+  }
+
+  @Override
+  public void setUp() {
+    injector = null;
+  }
+
+  @Override
+  public final void tearDown() {
+    if (injector == null) {
+      return;
+    }
+
+    injector.getInstance(UnitOfWork.class).end();
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  private static DataSource getDataSource() {
+    final JDBCDataSource dataSource = new JDBCDataSource();
+    dataSource.setDatabase("jdbc:hsqldb:mem:persistence");
+    dataSource.setUser("sa");
+    dataSource.setPassword("");
+    return dataSource;
+  }
+
+  private void startPersistService(boolean passDataSource) {
+    final DataSource dataSource = getDataSource();
+
+    injector = Guice.createInjector(new DBModule(dataSource, passDataSource));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+  public void testWorksIfPassDataSource() {
+    startPersistService(true);
+  }
+
+  public void testFailsIfNoDataSource() {
+    try {
+      startPersistService(false);
+      fail();
+    } catch (PersistenceException ex) {
+      // Expected
+      injector = null;
+    }
+  }
+
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.java b/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.java
new file mode 100644
index 0000000..1a61e41
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class EntityManagerFactoryProvisionTest extends TestCase {
+  private Injector injector;
+
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+  }
+
+  public final void tearDown() {
+    injector.getInstance(UnitOfWork.class).end();
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testSessionCreateOnInjection() {
+
+    assertEquals("SINGLETON VIOLATION " + UnitOfWork.class.getName(),
+        injector.getInstance(UnitOfWork.class), injector.getInstance(UnitOfWork.class));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+
+    //obtain em
+    assertTrue(injector.getInstance(EntityManager.class).isOpen());
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest.java b/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest.java
new file mode 100644
index 0000000..733884f
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+/**
+ * A test around providing sessions (starting, closing etc.)
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class EntityManagerPerRequestProvisionTest extends TestCase {
+  private Injector injector;
+
+  @Override
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+
+    injector.getInstance(UnitOfWork.class).begin();
+  }
+
+  @Override
+  public final void tearDown() {
+    injector.getInstance(UnitOfWork.class).end();
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testEntityManagerLifecyclePerTxn() {
+    //obtain em
+    JpaDao dao = injector.getInstance(JpaDao.class);
+
+    //obtain same em again (bound to txn)
+    JpaTestEntity te = new JpaTestEntity();
+
+    dao.persist(te);
+
+    //im not sure this hack works...
+    assertEquals("Entity managers closed inside same thread-scope",
+        injector.getInstance(EntityManager.class), JpaDao.em);
+
+    //try to start a new em in a new txn
+    dao = injector.getInstance(JpaDao.class);
+
+    assertTrue("EntityManager was closed and reopened around txn"
+        + " (persistent object does not persist)", dao.contains(te));
+  }
+
+  public void testEntityManagerLifecyclePerTxn2() {
+    //obtain em
+    JpaDao dao = injector.getInstance(JpaDao.class);
+
+    //obtain same em again (bound to txn)
+    JpaTestEntity te = new JpaTestEntity();
+
+    dao.persist(te);
+
+    //im not sure this hack works...
+    assertEquals("Duplicate entity managers crossing-scope",
+        injector.getInstance(EntityManager.class), JpaDao.em);
+    assertEquals("Duplicate entity managers crossing-scope",
+        injector.getInstance(EntityManager.class), JpaDao.em);
+
+    //try to start a new em in a new txn
+    dao = injector.getInstance(JpaDao.class);
+
+    assertTrue("EntityManager was closed and reopened around txn"
+        + " (persistent object doesnt persist)", dao.contains(te));
+  }
+
+  public static class JpaDao {
+    static EntityManager em;
+
+    @Inject
+    public JpaDao(EntityManager em) {
+      JpaDao.em = em;
+    }
+
+    @Transactional
+    public <T> void persist(T t) {
+      assertTrue("em is not open!", em.isOpen());
+      assertTrue("no active txn!", em.getTransaction().isActive());
+      em.persist(t);
+
+      assertTrue("Persisting object failed", em.contains(t));
+    }
+
+    @Transactional
+    public <T> boolean contains(T t) {
+      return em.contains(t);
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerProvisionTest.java b/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerProvisionTest.java
new file mode 100644
index 0000000..fbde101
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerProvisionTest.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+
+import junit.framework.TestCase;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+/**
+ * A test around providing sessions (starting, closing etc.)
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class EntityManagerProvisionTest extends TestCase {
+  private Injector injector;
+
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  public final void tearDown() {
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testEntityManagerLifecyclePerTxn() {
+    //obtain em
+    JpaDao dao = injector.getInstance(JpaDao.class);
+
+    //obtain same em again (bound to txn)
+    JpaTestEntity te = new JpaTestEntity();
+
+    dao.persist(te);
+
+    //im not sure this hack works...
+    assertFalse("Duplicate entity managers crossing-scope",
+        dao.lastEm.equals(injector.getInstance(EntityManager.class)));
+
+    //try to start a new em in a new txn
+    dao = injector.getInstance(JpaDao.class);
+
+    assertFalse("EntityManager wasnt closed and reopened properly around txn"
+        + " (persistent object persists)", dao.contains(te));
+  }
+
+  public void testEntityManagerLifecyclePerTxn2() {
+    //obtain em
+    JpaDao dao = injector.getInstance(JpaDao.class);
+
+    //obtain same em again (bound to txn)
+    JpaTestEntity te = new JpaTestEntity();
+
+    dao.persist(te);
+
+    //im not sure this hack works...
+    assertFalse("Duplicate entity managers crossing-scope",
+        dao.lastEm.equals(injector.getInstance(EntityManager.class)));
+
+    //try to start a new em in a new txn
+    dao = injector.getInstance(JpaDao.class);
+
+    assertFalse("EntityManager wasnt closed and reopened properly around txn"
+        + " (persistent object persists)", dao.contains(te));
+  }
+
+  public static class JpaDao {
+    private final Provider<EntityManager> em;
+    EntityManager lastEm;
+
+    @Inject
+    public JpaDao(Provider<EntityManager> em) {
+     this.em = em;
+    }
+
+    @Transactional
+    public <T> void persist(T t) {
+      lastEm = em.get();
+      assertTrue("em is not open!", lastEm.isOpen());
+      assertTrue("no active txn!", lastEm.getTransaction().isActive());
+      lastEm.persist(t);
+
+      assertTrue("Persisting object failed", lastEm.contains(t));
+    }
+
+    @Transactional
+    public <T> boolean contains(T t) {
+      if (null == lastEm) {
+        lastEm = em.get();
+      }
+      return lastEm.contains(t);
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/JoiningLocalTransactionsTest.java b/extensions/persist/test/com/google/inject/persist/jpa/JoiningLocalTransactionsTest.java
new file mode 100644
index 0000000..a1e4e80
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/JoiningLocalTransactionsTest.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.NoResultException;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class JoiningLocalTransactionsTest extends TestCase {
+  private Injector injector;
+  private static final String UNIQUE_TEXT = JoiningLocalTransactionsTest.class + "some unique text"
+      + new Date();
+  private static final String TRANSIENT_UNIQUE_TEXT = JoiningLocalTransactionsTest.class
+      + "some other unique text" + new Date();
+
+  @Override
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  //cleanup entitymanager in case some of the rollback tests left it in an open state
+  @Override
+  public final void tearDown() {
+    injector.getInstance(UnitOfWork.class).end();
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testSimpleTransaction() {
+    injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class)
+        .runOperationInTxn();
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse("txn was not closed by transactional service",
+        em.getTransaction().isActive());
+
+    //test that the data has been stored
+    Object result = em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT).getSingleResult();
+    injector.getInstance(UnitOfWork.class).end();
+
+    assertTrue("odd result returned fatal", result instanceof JpaTestEntity);
+
+    assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT,
+        ((JpaTestEntity) result).getText());
+  }
+
+  public void testSimpleTransactionRollbackOnChecked() {
+    try {
+      injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class)
+          .runOperationInTxnThrowingChecked();
+    } catch (IOException e) {
+      //ignore
+      injector.getInstance(UnitOfWork.class).end();
+    }
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+
+    assertFalse("EM was not closed by transactional service (rollback didnt happen?)",
+        em.getTransaction().isActive());
+
+    //test that the data has been stored
+    try {
+      Object result = em.createQuery("from JpaTestEntity where text = :text")
+          .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult();
+      injector.getInstance(UnitOfWork.class).end();
+      fail("a result was returned! rollback sure didnt happen!!!");
+    } catch (NoResultException e) { }
+  }
+
+  public void testSimpleTransactionRollbackOnUnchecked() {
+    try {
+      injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class)
+          .runOperationInTxnThrowingUnchecked();
+    } catch (RuntimeException re) {
+      //ignore
+      injector.getInstance(UnitOfWork.class).end();
+    }
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse("Session was not closed by transactional service (rollback didnt happen?)",
+        em.getTransaction().isActive());
+
+    try {
+      Object result = em.createQuery("from JpaTestEntity where text = :text")
+          .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult();
+      injector.getInstance(UnitOfWork.class).end();
+      fail("a result was returned! rollback sure didnt happen!!!");
+    } catch (NoResultException e) {}
+  }
+
+  public static class TransactionalObject {
+    private final EntityManager em;
+
+    @Inject
+    public TransactionalObject(EntityManager em) {
+      this.em = em;
+    }
+
+    @Transactional
+    public void runOperationInTxn() {
+      runOperationInTxnInternal();
+    }
+
+    @Transactional(rollbackOn = IOException.class)
+    public void runOperationInTxnInternal() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT);
+      em.persist(entity);
+    }
+
+    @Transactional(rollbackOn = IOException.class)
+    public void runOperationInTxnThrowingChecked() throws IOException {
+      runOperationInTxnThrowingCheckedInternal();
+    }
+
+    @Transactional
+    private void runOperationInTxnThrowingCheckedInternal() throws IOException {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(TRANSIENT_UNIQUE_TEXT);
+      em.persist(entity);
+
+      throw new IOException();
+    }
+
+    @Transactional
+    public void runOperationInTxnThrowingUnchecked() {
+      runOperationInTxnThrowingUncheckedInternal();
+    }
+
+    @Transactional(rollbackOn = IOException.class)
+    public void runOperationInTxnThrowingUncheckedInternal() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(TRANSIENT_UNIQUE_TEXT);
+      em.persist(entity);
+
+      throw new IllegalStateException();
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/JpaParentTestEntity.java b/extensions/persist/test/com/google/inject/persist/jpa/JpaParentTestEntity.java
new file mode 100644
index 0000000..600e088
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/JpaParentTestEntity.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+
+/**
+ * Created with IntelliJ IDEA.
+ * On: 2/06/2007
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ * @since 1.0
+ */
+@Entity
+public class JpaParentTestEntity {
+    private Long id;
+    private List<JpaTestEntity> children = new ArrayList<JpaTestEntity>();
+
+    @Id
+    @GeneratedValue
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    @OneToMany
+    public List<JpaTestEntity> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<JpaTestEntity> children) {
+        this.children = children;
+    }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/JpaPersistServiceTest.java b/extensions/persist/test/com/google/inject/persist/jpa/JpaPersistServiceTest.java
new file mode 100644
index 0000000..e099a5e
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/JpaPersistServiceTest.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2014 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.inject.persist.jpa;
+
+import junit.framework.TestCase;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Properties;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.spi.PersistenceProvider;
+
+public class JpaPersistServiceTest extends TestCase {
+
+  private static final String PERSISTENCE_UNIT_NAME = "test_persistence_unit_name";
+  private static final Properties PERSISTENCE_PROPERTIES = new Properties();
+
+  private final JpaPersistService sut = new JpaPersistService(PERSISTENCE_UNIT_NAME, PERSISTENCE_PROPERTIES);
+  private final PersistenceProvider provider = mock(PersistenceProvider.class);
+  private final EntityManagerFactory factory = mock(EntityManagerFactory.class);
+  private final EntityManager entityManager = mock(EntityManager.class);
+
+  @Override
+  public void setUp() throws Exception {
+    when(provider.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, PERSISTENCE_PROPERTIES)).thenReturn(factory);
+    when(factory.createEntityManager()).thenReturn(entityManager);
+  }
+
+  public void test_givenErrorOnEntityManagerClose_whenEndIsCalled_thenEntityManagerIsRemoved() {
+    sut.start(factory);
+    sut.begin();
+
+    // arrange an exception on sut.end(), which invokes entityManager.close()
+    doThrow(SimulatedException.class).when(entityManager).close();
+    try {
+      sut.end();
+      fail("Exception expected");
+    }
+    catch (SimulatedException expected) {
+      assertThat(sut.isWorking(), is(false));
+    }
+  }
+
+  private class SimulatedException extends RuntimeException {
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/JpaTestEntity.java b/extensions/persist/test/com/google/inject/persist/jpa/JpaTestEntity.java
new file mode 100644
index 0000000..8fa6fd1
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/JpaTestEntity.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+/** @author Dhanji R. Prasanna (dhanji@gmail.com) */
+@Entity
+public class JpaTestEntity {
+  private Long id;
+  private String text;
+
+  @Id @GeneratedValue
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public String getText() {
+    return text;
+  }
+
+  public void setText(String text) {
+    this.text = text;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    JpaTestEntity that = (JpaTestEntity) o;
+
+    if (id != null ? !id.equals(that.id) : that.id != null) {
+      return false;
+    }
+    if (text != null ? !text.equals(that.text) : that.text != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = id != null ? id.hashCode() : 0;
+    result = 31 * result + (text != null ? text.hashCode() : 0);
+    return result;
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/JpaWorkManagerTest.java b/extensions/persist/test/com/google/inject/persist/jpa/JpaWorkManagerTest.java
new file mode 100644
index 0000000..84dff07
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/JpaWorkManagerTest.java
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+import org.hibernate.HibernateException;
+
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Query;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class JpaWorkManagerTest extends TestCase {
+  private Injector injector;
+  private static final String UNIQUE_TEXT_3 = JpaWorkManagerTest.class.getSimpleName()
+      + "CONSTRAINT_VIOLATING some other unique text" + new Date();
+
+  @Override
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  @Override
+  public void tearDown() {
+    try {
+      injector.getInstance(EntityManagerFactory.class).close();
+    } catch(HibernateException ex) {
+        // Expected if the persist service has already been stopped.
+    }
+  }
+
+  public void testWorkManagerInSession() {
+    injector.getInstance(UnitOfWork.class).begin();
+    try {
+      injector.getInstance(TransactionalObject.class).runOperationInTxn();
+    } finally {
+      injector.getInstance(UnitOfWork.class).end();
+
+    }
+
+    injector.getInstance(UnitOfWork.class).begin();
+    injector.getInstance(EntityManager.class).getTransaction().begin();
+    try {
+      final Query query = injector.getInstance(EntityManager.class)
+          .createQuery("select e from JpaTestEntity as e where text = :text");
+
+      query.setParameter("text", UNIQUE_TEXT_3);
+      final Object o = query.getSingleResult();
+
+      assertNotNull("no result!!", o);
+      assertTrue("Unknown type returned " + o.getClass(), o instanceof JpaTestEntity);
+      JpaTestEntity ent = (JpaTestEntity) o;
+
+      assertEquals("Incorrect result returned or not persisted properly" + ent.getText(),
+          UNIQUE_TEXT_3, ent.getText());
+
+    } finally {
+      injector.getInstance(EntityManager.class).getTransaction().commit();
+      injector.getInstance(UnitOfWork.class).end();
+    }
+  }
+
+  public void testCloseMoreThanOnce() {
+    injector.getInstance(PersistService.class).stop();
+
+    try {
+      injector.getInstance(PersistService.class).stop();
+      fail();
+    } catch (IllegalStateException e) {
+      // Ignored.
+    }
+  }
+
+  public static class TransactionalObject {
+    @Inject EntityManager em;
+
+    @Transactional
+    public void runOperationInTxn() {
+      JpaTestEntity testEntity = new JpaTestEntity();
+
+      testEntity.setText(UNIQUE_TEXT_3);
+      em.persist(testEntity);
+    }
+
+    @Transactional
+    public void runOperationInTxnError() {
+
+      JpaTestEntity testEntity = new JpaTestEntity();
+
+      testEntity.setText(UNIQUE_TEXT_3 + "transient never in db!" + hashCode());
+      em.persist(testEntity);
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossRequestTest.java b/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossRequestTest.java
new file mode 100644
index 0000000..76e3f7f
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossRequestTest.java
@@ -0,0 +1,231 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.name.Named;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+import com.google.inject.persist.finder.Finder;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.NoResultException;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class ManagedLocalTransactionsAcrossRequestTest extends TestCase {
+  private Injector injector;
+  private static final String UNIQUE_TEXT = "some unique text" + new Date();
+  private static final String UNIQUE_TEXT_MERGE = "meRG_Esome unique text" + new Date();
+  private static final String UNIQUE_TEXT_MERGE_FORDF = "aSdoaksdoaksdmeRG_Esome unique text"
+      + new Date();
+  private static final String TRANSIENT_UNIQUE_TEXT = "some other unique text" + new Date();
+
+  @Override
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  @Override
+  public final void tearDown() {
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testSimpleTransaction() {
+    injector.getInstance(TransactionalObject.class).runOperationInTxn();
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse(em.getTransaction().isActive());
+
+    //test that the data has been stored
+    Object result = em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT).getSingleResult();
+    injector.getInstance(UnitOfWork.class).end();
+
+    assertTrue("odd result returned fatal", result instanceof JpaTestEntity);
+
+    assertEquals("queried entity did not match--did automatic txn fail?",
+        UNIQUE_TEXT, ((JpaTestEntity) result).getText());
+    injector.getInstance(UnitOfWork.class).end();
+
+  }
+
+  public void testSimpleTransactionWithMerge() {
+    EntityManager emOrig = injector.getInstance(EntityManager.class);
+    JpaTestEntity entity = injector.getInstance(TransactionalObject.class)
+        .runOperationInTxnWithMerge();
+
+    assertNotNull("Entity was not given an id (was not persisted correctly?)", entity.getId());
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse(em.getTransaction().isActive());
+
+    //test that the data has been stored
+    assertTrue("Em was closed after txn!", em.isOpen());
+    assertEquals("Em was not kept open across txns", emOrig, em);
+    assertTrue("Merge did not store state or did not return persistent copy", em.contains(entity));
+
+    Object result = em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT_MERGE).getSingleResult();
+    injector.getInstance(UnitOfWork.class).end();
+
+    assertTrue(result instanceof JpaTestEntity);
+
+    assertEquals("queried entity did not match--did automatic txn fail?",
+        UNIQUE_TEXT_MERGE, ((JpaTestEntity) result).getText());
+    injector.getInstance(UnitOfWork.class).end();
+
+  }
+
+  public void disabled_testSimpleTransactionWithMergeAndDF() {
+    EntityManager emOrig = injector.getInstance(EntityManager.class);
+    JpaTestEntity entity = injector.getInstance(TransactionalObject.class)
+        .runOperationInTxnWithMergeForDf();
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse("txn was not closed by transactional service", em.getTransaction().isActive());
+
+    //test that the data has been stored
+    assertTrue("Em was closed after txn!", em.isOpen());
+    assertEquals("Em was not kept open across txns", emOrig, em);
+    assertTrue("Merge did not store state or did not return persistent copy", em.contains(entity));
+
+    Object result = injector.getInstance(TransactionalObject.class).find(UNIQUE_TEXT_MERGE_FORDF);
+    injector.getInstance(UnitOfWork.class).end();
+
+    assertNotNull(result);
+    assertTrue(result instanceof JpaTestEntity);
+
+    assertEquals("queried entity did not match--did automatic txn fail?",
+        UNIQUE_TEXT_MERGE_FORDF, ((JpaTestEntity) result).getText());
+    injector.getInstance(UnitOfWork.class).end();
+
+  }
+
+  public void testSimpleTransactionRollbackOnChecked() {
+    try {
+      injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingChecked();
+    } catch (IOException e) {
+      //ignore
+      injector.getInstance(UnitOfWork.class).end();
+    }
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+
+    assertFalse("Previous EM was not closed by transactional service (rollback didnt happen?)",
+        em.getTransaction().isActive());
+
+    //test that the data has been stored
+    try {
+      Object result = em.createQuery("from JpaTestEntity where text = :text")
+          .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult();
+      injector.getInstance(UnitOfWork.class).end();
+      fail();
+    } catch (NoResultException e) {}
+
+    injector.getInstance(UnitOfWork.class).end();
+  }
+
+  public void testSimpleTransactionRollbackOnUnchecked() {
+    try {
+      injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingUnchecked();
+    } catch (RuntimeException re) {
+      //ignore
+      injector.getInstance(UnitOfWork.class).end();
+    }
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse("Session was not closed by transactional service (rollback didnt happen?)",
+        em.getTransaction().isActive());
+
+    try {
+      Object result = em.createQuery("from JpaTestEntity where text = :text")
+          .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult();
+      injector.getInstance(UnitOfWork.class).end();
+      fail();
+    } catch (NoResultException e) {}
+
+    injector.getInstance(UnitOfWork.class).end();
+  }
+
+  public static class TransactionalObject {
+    private final EntityManager em;
+
+    @Inject
+    public TransactionalObject(EntityManager em) {
+      this.em = em;
+    }
+
+    @Transactional
+    public void runOperationInTxn() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT);
+      em.persist(entity);
+    }
+
+    @Transactional
+    public JpaTestEntity runOperationInTxnWithMerge() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT_MERGE);
+      return em.merge(entity);
+    }
+
+    @Transactional
+    public JpaTestEntity runOperationInTxnWithMergeForDf() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT_MERGE_FORDF);
+      return em.merge(entity);
+    }
+
+    @Transactional(rollbackOn = IOException.class)
+    public void runOperationInTxnThrowingChecked() throws IOException {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(TRANSIENT_UNIQUE_TEXT);
+      em.persist(entity);
+
+      throw new IOException();
+    }
+
+    @Transactional
+    public void runOperationInTxnThrowingUnchecked() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(TRANSIENT_UNIQUE_TEXT);
+      em.persist(entity);
+
+      throw new IllegalStateException();
+    }
+
+    @Finder(query = "from JpaTestEntity where text = :text")
+    public JpaTestEntity find(@Named("text") String text) {
+      return null;
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java b/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java
new file mode 100644
index 0000000..2ba9195
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.NoResultException;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class ManagedLocalTransactionsTest extends TestCase {
+  private Injector injector;
+  private static final String UNIQUE_TEXT = "some unique text" + new Date();
+  private static final String UNIQUE_TEXT_MERGE = "meRG_Esome unique text" + new Date();
+  private static final String TRANSIENT_UNIQUE_TEXT = "some other unique text" + new Date();
+
+  @Override
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  @Override
+  public final void tearDown() {
+    injector.getInstance(UnitOfWork.class).end();
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testSimpleTransaction() {
+    injector.getInstance(TransactionalObject.class).runOperationInTxn();
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse("txn was not closed by transactional service", em.getTransaction().isActive());
+
+    //test that the data has been stored
+    Object result = em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT).getSingleResult();
+    injector.getInstance(UnitOfWork.class).end();
+
+    assertTrue("odd result returned fatal", result instanceof JpaTestEntity);
+
+    assertEquals("queried entity did not match--did automatic txn fail?",
+        UNIQUE_TEXT, ((JpaTestEntity) result).getText());
+  }
+
+  public void testSimpleTransactionWithMerge() {
+    JpaTestEntity entity = injector.getInstance(TransactionalObject.class)
+        .runOperationInTxnWithMerge();
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse("txn was not closed by transactional service", em.getTransaction().isActive());
+
+    //test that the data has been stored
+    assertTrue("Em was closed after txn!", em.isOpen());
+
+    Object result = em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT_MERGE).getSingleResult();
+    injector.getInstance(UnitOfWork.class).end();
+
+    assertTrue(result instanceof JpaTestEntity);
+
+    assertEquals("queried entity did not match--did automatic txn fail?",
+        UNIQUE_TEXT_MERGE, ((JpaTestEntity) result).getText());
+  }
+
+  public void testSimpleTransactionRollbackOnChecked() {
+    try {
+      injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingChecked();
+    } catch (IOException e) {
+      //ignore
+      injector.getInstance(UnitOfWork.class).end();
+    }
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+
+    assertFalse("Previous EM was not closed by transactional service (rollback didnt happen?)",
+        em.getTransaction().isActive());
+
+    //test that the data has been stored
+    try {
+      Object result = em.createQuery("from JpaTestEntity where text = :text")
+          .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult();
+      injector.getInstance(UnitOfWork.class).end();
+      fail("a result was returned! rollback sure didnt happen!!!");
+    } catch (NoResultException e) {}
+  }
+
+  public void testSimpleTransactionRollbackOnUnchecked() {
+    try {
+      injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingUnchecked();
+    } catch (RuntimeException re) {
+      //ignore
+      injector.getInstance(UnitOfWork.class).end();
+    }
+
+    EntityManager em = injector.getInstance(EntityManager.class);
+    assertFalse("Session was not closed by transactional service (rollback didnt happen?)",
+        em.getTransaction().isActive());
+
+    try {
+      Object result = em.createQuery("from JpaTestEntity where text = :text")
+          .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult();
+      injector.getInstance(UnitOfWork.class).end();
+      fail("a result was returned! rollback sure didnt happen!!!");
+    } catch (NoResultException e) {}
+  }
+
+  public static class TransactionalObject {
+    private final EntityManager em;
+
+    @Inject
+    public TransactionalObject(EntityManager em) {
+      this.em = em;
+    }
+
+    @Transactional
+    public void runOperationInTxn() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT);
+      em.persist(entity);
+    }
+
+    @Transactional
+    public JpaTestEntity runOperationInTxnWithMerge() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT_MERGE);
+      return em.merge(entity);
+    }
+
+    @Transactional(rollbackOn = IOException.class)
+    public void runOperationInTxnThrowingChecked() throws IOException {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(TRANSIENT_UNIQUE_TEXT);
+      em.persist(entity);
+
+      throw new IOException();
+    }
+
+    @Transactional
+    public void runOperationInTxnThrowingUnchecked() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(TRANSIENT_UNIQUE_TEXT);
+      em.persist(entity);
+
+      throw new IllegalStateException();
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTest.java b/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTest.java
new file mode 100644
index 0000000..ecd2999
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTest.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+
+import junit.framework.TestCase;
+
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceException;
+
+/**
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class ManualLocalTransactionsConfidenceTest extends TestCase {
+  private Injector injector;
+  private static final String UNIQUE_TEXT_3 =
+      ManualLocalTransactionsConfidenceTest.class.getSimpleName()
+          + "CONSTRAINT_VIOLATING some other unique text" + new Date();
+
+  @Override
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  @Override
+  public final void tearDown() {
+    injector.getInstance(PersistService.class).stop();
+  }
+
+  public void testThrowingCleanupInterceptorConfidence() {
+    Exception e = null;
+    try {
+      System.out.println(
+          "\n\n******************************* EXPECTED EXCEPTION NORMAL TEST BEHAVIOR **********");
+      injector.getInstance(TransactionalObject.class).runOperationInTxn();
+      fail();
+    } catch (RuntimeException re) {
+      e = re;
+      System.out.println(
+          "\n\n******************************* EXPECTED EXCEPTION NORMAL TEST BEHAVIOR **********");
+      re.printStackTrace(System.out);
+      System.out.println(
+          "\n\n**********************************************************************************");
+    }
+
+    assertNotNull("No exception was thrown!", e);
+    assertTrue("Exception thrown was not what was expected (i.e. commit-time)",
+        e instanceof PersistenceException);
+  }
+
+  public static class TransactionalObject {
+    @Inject EntityManager em;
+
+    @Transactional
+    public void runOperationInTxn() {
+      JpaParentTestEntity entity = new JpaParentTestEntity();
+      JpaTestEntity child = new JpaTestEntity();
+
+      child.setText(UNIQUE_TEXT_3);
+      em.persist(child);
+
+      entity.getChildren().add(child);
+      em.persist(entity);
+
+      entity = new JpaParentTestEntity();
+      entity.getChildren().add(child);
+      em.persist(entity);
+    }
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsTest.java b/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsTest.java
new file mode 100644
index 0000000..2baa345
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsTest.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+/**
+ * For instance, a session-per-request strategy will control the opening and closing of the EM at
+ * its own (manual) discretion. As opposed to a transactional unit of work.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+
+public class ManualLocalTransactionsTest extends TestCase {
+  private Injector injector;
+  private static final String UNIQUE_TEXT = "some unique text" + new Date();
+  private static final String UNIQUE_TEXT_2 = "some other unique text" + new Date();
+
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  public void tearDown() {
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testSimpleCrossTxnWork() {
+    injector.getInstance(UnitOfWork.class).begin();
+
+    //pretend that the request was started here
+    EntityManager em = injector.getInstance(EntityManager.class);
+
+    JpaTestEntity entity = injector.getInstance(TransactionalObject.class).runOperationInTxn();
+    injector.getInstance(TransactionalObject.class).runOperationInTxn2();
+
+    //persisted entity should remain in the same em (which should still be open)
+    assertTrue("EntityManager  appears to have been closed across txns!",
+        injector.getInstance(EntityManager.class).contains(entity));
+    assertTrue("EntityManager  appears to have been closed across txns!", em.contains(entity));
+    assertTrue("EntityManager appears to have been closed across txns!", em.isOpen());
+
+    injector.getInstance(UnitOfWork.class).end();
+    injector.getInstance(UnitOfWork.class).begin();
+
+    //try to query them back out
+    em = injector.getInstance(EntityManager.class);
+    assertNotNull(em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT).getSingleResult());
+    assertNotNull(em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT_2).getSingleResult());
+    em.close();
+
+    assertFalse(em.isOpen());
+  }
+
+  public static class TransactionalObject {
+    @Inject EntityManager em;
+
+    @Transactional
+    public JpaTestEntity runOperationInTxn() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT);
+      em.persist(entity);
+
+      return entity;
+    }
+
+    @Transactional
+    public void runOperationInTxn2() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT_2);
+      em.persist(entity);
+    }
+
+  }
+}
diff --git a/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMatcherTest.java b/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMatcherTest.java
new file mode 100644
index 0000000..4290d1d
--- /dev/null
+++ b/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMatcherTest.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2010 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.inject.persist.jpa;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+
+import junit.framework.TestCase;
+
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+/**
+ * Created with IntelliJ IDEA. On: 2/06/2007
+ *
+ * For instance, a session-per-request strategy will control the opening and closing of the EM at
+ * its own (manual) discretion. As opposed to a transactional unit of work.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ * @since 1.0
+ */
+
+public class ManualLocalTransactionsWithCustomMatcherTest extends TestCase {
+  private Injector injector;
+  private static final String UNIQUE_TEXT = "some unique text" + new Date();
+  private static final String UNIQUE_TEXT_2 = "some other unique text" + new Date();
+
+  @Override
+  public void setUp() {
+    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
+
+    //startup persistence
+    injector.getInstance(PersistService.class).start();
+  }
+
+  @Override
+  public void tearDown() {
+    injector.getInstance(EntityManagerFactory.class).close();
+  }
+
+  public void testSimpleCrossTxnWork() {
+    //pretend that the request was started here
+    EntityManager em = injector.getInstance(EntityManager.class);
+
+    JpaTestEntity entity = injector
+        .getInstance(ManualLocalTransactionsWithCustomMatcherTest.TransactionalObject.class)
+        .runOperationInTxn();
+    injector.getInstance(ManualLocalTransactionsWithCustomMatcherTest.TransactionalObject.class)
+        .runOperationInTxn2();
+
+    //persisted entity should remain in the same em (which should still be open)
+    assertTrue("EntityManager  appears to have been closed across txns!",
+        injector.getInstance(EntityManager.class).contains(entity));
+    assertTrue("EntityManager  appears to have been closed across txns!", em.contains(entity));
+    assertTrue("EntityManager appears to have been closed across txns!", em.isOpen());
+
+    injector.getInstance(UnitOfWork.class).end();
+
+    //try to query them back out
+    em = injector.getInstance(EntityManager.class);
+    assertNotNull(em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT).getSingleResult());
+    assertNotNull(em.createQuery("from JpaTestEntity where text = :text")
+        .setParameter("text", UNIQUE_TEXT_2).getSingleResult());
+    em.close();
+  }
+
+  public static class TransactionalObject {
+    @Inject EntityManager em;
+
+    @Transactional
+    public JpaTestEntity runOperationInTxn() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT);
+      em.persist(entity);
+
+      return entity;
+    }
+
+    @Transactional
+    public void runOperationInTxn2() {
+      JpaTestEntity entity = new JpaTestEntity();
+      entity.setText(UNIQUE_TEXT_2);
+      em.persist(entity);
+    }
+
+  }
+}
diff --git a/extensions/persist/test/log4j.properties b/extensions/persist/test/log4j.properties
new file mode 100644
index 0000000..1654ecd
--- /dev/null
+++ b/extensions/persist/test/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=warn, console
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.Target=System.out
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%p [%c{1}] - %m %n
diff --git a/extensions/pom.xml b/extensions/pom.xml
new file mode 100644
index 0000000..283baa2
--- /dev/null
+++ b/extensions/pom.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject</groupId>
+    <artifactId>guice-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <packaging>pom</packaging>
+
+  <groupId>com.google.inject.extensions</groupId>
+  <artifactId>extensions-parent</artifactId>
+
+  <name>Google Guice - Extensions</name>
+
+  <modules>
+    <module>assistedinject</module>
+    <!-- TODO(cgruber): Comment out dagger-adapter module if guice releases before dagger 2.x -->
+    <module>dagger-adapter</module>
+    <module>grapher</module>
+    <module>jmx</module>
+    <module>jndi</module>
+    <module>multibindings</module>
+    <module>persist</module>
+    <module>servlet</module>
+    <module>spring</module>
+    <module>struts2</module>
+    <module>testlib</module>
+    <module>throwingproviders</module>
+<!--
+ |  not yet promoted...
+- -
+    <module>mini</module>
+    <module>service</module>
+-->
+  </modules>
+
+  <dependencies>
+    <!--
+     | All extensions depend on the core
+    -->
+    <dependency>
+      <groupId>com.google.inject</groupId>
+      <artifactId>guice</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <!--
+     | Some extension tests depend on the core tests
+    -->
+    <dependency>
+      <groupId>com.google.inject</groupId>
+      <artifactId>guice</artifactId>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+    <!--
+     | Some extension tests depend on guava test libs which are not inherited
+     | from test scope.
+    -->
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava-testlib</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!--
+     | Some extension tests depend on cglib which is not embedded
+     | in an execution that doesn't include package.
+    -->
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!--
+       | Add standard LICENSE and NOTICE files
+      -->
+      <plugin>
+        <artifactId>maven-remote-resources-plugin</artifactId>
+      </plugin>
+      <!--
+       | Enable Java6 conformance checks
+      -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>animal-sniffer-maven-plugin</artifactId>
+      </plugin>
+      <!--
+       | Add OSGi manifest: extensions are fragments that attach to the core
+      -->
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Fragment-Host>com.google.inject</Fragment-Host>
+          </instructions>
+        </configuration>
+      </plugin>
+      <!--
+       | Generate sources jar
+      -->
+      <plugin>
+        <artifactId>maven-source-plugin</artifactId>
+      </plugin>
+      <!--
+       | Generate javadoc jar
+      -->
+      <plugin>
+        <artifactId>maven-javadoc-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/extensions/service/pom.xml b/extensions/service/pom.xml
new file mode 100644
index 0000000..2d96e0d
--- /dev/null
+++ b/extensions/service/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>guice-service</artifactId>
+
+  <name>Google Guice - Extensions - Service</name>
+
+</project>
diff --git a/extensions/service/src/com/google/inject/service/AsyncService.java b/extensions/service/src/com/google/inject/service/AsyncService.java
new file mode 100644
index 0000000..fe0c3a5
--- /dev/null
+++ b/extensions/service/src/com/google/inject/service/AsyncService.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2010 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.inject.service;
+
+import com.google.common.base.Preconditions;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+
+/**
+ * An asynchronous implementation of {@link com.google.inject.service.Service}
+ * that provides convenience callbacks to create your own services.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public abstract class AsyncService implements Service {
+  private static final Runnable DO_NOTHING = new Runnable() {
+    @Override public void run() {}
+  };
+
+  private final ExecutorService executor;
+
+  private volatile State state;
+
+  public AsyncService(ExecutorService executor) {
+    this.executor = executor;
+  }
+
+  public synchronized final Future<State> start() {
+    Preconditions.checkState(state != State.STOPPED,
+        "Cannot restart a service that has been stopped");
+
+    // Starts are idempotent.
+    if (state == State.STARTED) {
+      return new FutureTask<State>(DO_NOTHING, State.STARTED);
+    }
+
+    return executor.submit(new Callable<State>() {
+      public State call() {
+        onStart();
+        return state = State.STARTED;
+      }
+    });
+  }
+
+  /**
+   * Called back when this service must do its start work. Typically occurs
+   * in a background thread. The result of this method is returned to the
+   * original caller of {@link Service#start()} and can thus be used to
+   * return a status message after start completes (or fails as the case
+   * may be).
+   */
+  protected abstract void onStart();
+
+  public synchronized final Future<State> stop() {
+    Preconditions.checkState(state != null, "Must start this service before you stop it!");
+
+    // Likewise, stops are idempotent.
+    if (state == State.STOPPED) {
+      return new FutureTask<State>(DO_NOTHING, State.STOPPED);
+    }
+
+    return executor.submit(new Callable<State>() {
+      public State call() {
+        onStop();
+        return state = State.STOPPED;
+      }
+    });
+  }
+
+  /**
+   * Called back when this service must shutdown. Typically occurs
+   * in a background thread. The result of this method is returned to the
+   * original caller of {@link Service#stop()} and can thus be used to
+   * return a status message after stop completes (or fails as the case
+   * may be).
+   */
+  protected abstract void onStop();
+
+  public final State state() {
+    return state;
+  }
+}
diff --git a/extensions/service/src/com/google/inject/service/CompositeService.java b/extensions/service/src/com/google/inject/service/CompositeService.java
new file mode 100644
index 0000000..13e8b3d
--- /dev/null
+++ b/extensions/service/src/com/google/inject/service/CompositeService.java
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 2010 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.inject.service;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+
+/**
+ * A service that composes other services together in a fixed order.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class CompositeService {
+  private final Injector injector;
+
+  private final Set<Key<? extends Service>> services = Sets.newLinkedHashSet();
+
+  /**
+   * Represents the state of this composite service. Will equal FAILED
+   * even if only one component service fails to start or stop. In other
+   * words, all component services must start successfully for this
+   * service to be considered started and similarly for stopped.
+   */
+  private volatile Service.State compositeState;
+  private boolean composed;
+
+  @Inject
+  CompositeService(Injector injector) {
+    this.injector = injector;
+  }
+
+  public CompositeService add(Class<? extends Service> service) {
+    return add(Key.get(service));
+  }
+
+  public CompositeService add(Key<? extends Service> service) {
+    Preconditions.checkState(!composed,
+        "Cannot reuse a CompositeService after it has been compose()d. Please create a new one.");
+    // Verify that the binding exists. Throws an exception if not.
+    injector.getBinding(service);
+
+    services.add(service);
+    return this;
+  }
+
+  public Service compose() {
+    Preconditions.checkState(!composed,
+        "Cannot reuse a CompositeService after it has been compose()d. Please create a new one.");
+    composed = true;
+
+    // Defensive copy.
+    final List<Key<? extends Service>> services = ImmutableList.copyOf(this.services);
+
+    return new Service() {
+      public Future<State> start() {
+        final List<Future<State>> tasks = Lists.newArrayList();
+        for (Key<? extends Service> service : services) {
+          tasks.add(injector.getInstance(service).start());
+        }
+
+        return futureGet(tasks, State.STARTED);
+      }
+
+      public Future<State> stop() {
+        final List<Future<State>> tasks = Lists.newArrayList();
+        for (Key<? extends Service> service : services) {
+          tasks.add(injector.getInstance(service).stop());
+        }
+
+        return futureGet(tasks, State.STOPPED);
+      }
+
+      public State state() {
+        return compositeState;
+      }
+    };
+  }
+
+  private FutureTask<Service.State> futureGet(final List<Future<Service.State>> tasks,
+      final Service.State state) {
+    return new FutureTask<Service.State>(new Callable<Service.State>() {
+      public Service.State call() {
+        boolean ok = true;
+        for (Future<Service.State> task : tasks) {
+          try {
+            ok = state == task.get();
+          } catch (InterruptedException e) {
+            return compositeState = Service.State.FAILED;
+          } catch (ExecutionException e) {
+            return compositeState = Service.State.FAILED;
+          }
+        }
+
+        return compositeState = ok ? state : Service.State.FAILED;
+      }
+    });
+  }
+}
diff --git a/extensions/service/src/com/google/inject/service/Service.java b/extensions/service/src/com/google/inject/service/Service.java
new file mode 100644
index 0000000..fb7dc0d
--- /dev/null
+++ b/extensions/service/src/com/google/inject/service/Service.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2010 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.inject.service;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * An object with an operational state, asynchronous {@link #start()} and
+ * {@link #stop()} lifecycle methods to transition in and out of this state.
+ * Example services include http servers, RPC systems and timer tasks.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public interface Service {
+  /**
+   * If the service has already been started, this method returns
+   * immediately without taking action. A stopped service may not be restarted.
+   *
+   * @return a future for the startup result, regardless of whether this call
+   *     initiated startup. Calling {@link Future#get} will block until the
+   *     service has finished starting, and returns the resultant state. If
+   *     the service fails to start, {@link Future#get} will throw an {@link
+   *     ExecutionException}. If it has already finished starting,
+   *     {@link Future#get} returns immediately.
+   */
+  Future<State> start();
+
+  /**
+   * If the service is {@link State#STARTED} initiates service shutdown and
+   * returns immediately. If the service has already been stopped, this
+   * method returns immediately without taking action.
+   *
+   * @return a future for the shutdown result, regardless of whether this call
+   *     initiated shutdown. Calling {@link Future#get} will block until the
+   *     service has finished shutting down, and either returns {@link
+   *     State#STOPPED} or throws an {@link ExecutionException}. If it has
+   *     already finished stopping, {@link Future#get} returns immediately.
+   */
+  Future<State> stop();
+
+  /**
+   * Returns the current state of this service. One of {@link State} possible
+   * values, or null if this is a brand new object, i.e., has not been put into
+   * any state yet.
+   */
+  State state();
+
+  /**
+   * The lifecycle states of a service.
+   */
+  enum State { STARTED, STOPPED, FAILED }
+}
diff --git a/extensions/service/test/com/google/inject/service/SingleServiceIntegrationTest.java b/extensions/service/test/com/google/inject/service/SingleServiceIntegrationTest.java
new file mode 100644
index 0000000..9463b16
--- /dev/null
+++ b/extensions/service/test/com/google/inject/service/SingleServiceIntegrationTest.java
@@ -0,0 +1,80 @@
+package com.google.inject.service;
+
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests using Async Service.
+ */
+
+public class SingleServiceIntegrationTest extends TestCase {
+
+  public final void testAsyncServiceLifecycle() throws Exception {
+    ExecutorService executor = Executors.newSingleThreadExecutor();
+
+    final CountDownLatch startLatch = new CountDownLatch(1);
+    final CountDownLatch stopLatch = new CountDownLatch(1);
+    AsyncService service = new AsyncService(executor) {
+      @Override protected void onStart() {
+        assertEquals(1, startLatch.getCount());
+        assertEquals(1, stopLatch.getCount());
+
+        startLatch.countDown();
+      }
+
+      @Override protected void onStop() {
+        assertEquals(0, startLatch.getCount());
+        assertEquals(1, stopLatch.getCount());
+
+        stopLatch.countDown();
+      }
+    };
+
+    Future<?> future = service.start();
+    // This should not pass!  TODO(sameb): Why?  Looks like it should to me
+    assertTrue(startLatch.await(2, TimeUnit.SECONDS));
+    // onStart() is called before the state is set to STARTED, so we need
+    // to wait until the Future finishes to guarantee it really was started.
+    // This still manages to test what we want because the startLatch check
+    // is before this.
+    future.get(1, TimeUnit.SECONDS);
+
+    service.stop();
+    assertTrue(stopLatch.await(2, TimeUnit.SECONDS));
+
+    executor.shutdown();
+    assertEquals(0, startLatch.getCount());
+    assertEquals(0, stopLatch.getCount());
+  }
+
+  public final void testAsyncServiceBlockingLifecycle()
+      throws InterruptedException, ExecutionException, TimeoutException {
+    ExecutorService executor = Executors.newSingleThreadExecutor();
+
+    final AtomicInteger integer = new AtomicInteger(2);
+    AsyncService service = new AsyncService(executor) {
+      @Override protected void onStart() {
+        assertEquals(2, integer.getAndDecrement());
+      }
+
+      @Override protected void onStop() {
+        assertEquals(1, integer.getAndDecrement());
+      }
+    };
+
+    service.start().get(2, TimeUnit.SECONDS);
+    service.stop().get(2, TimeUnit.SECONDS);
+
+    executor.shutdown();
+    assertEquals(0, integer.get());
+  }
+}
diff --git a/extensions/servlet/build.properties b/extensions/servlet/build.properties
new file mode 100644
index 0000000..4a366b7
--- /dev/null
+++ b/extensions/servlet/build.properties
@@ -0,0 +1,8 @@
+lib.dir=../../lib
+ext.lib.dir=lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.servlet.AllTests
+module=com.google.inject.servlet
+fragment=true
diff --git a/extensions/servlet/build.xml b/extensions/servlet/build.xml
new file mode 100644
index 0000000..0ef5039
--- /dev/null
+++ b/extensions/servlet/build.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<project name="guice-servlet" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+  	<fileset dir="${ext.lib.dir}" includes="*.jar"/>
+    <fileset dir="${ext.lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/servlet/lib/build/servlet-api-2.5.jar b/extensions/servlet/lib/build/servlet-api-2.5.jar
new file mode 100644
index 0000000..fb52493
--- /dev/null
+++ b/extensions/servlet/lib/build/servlet-api-2.5.jar
Binary files differ
diff --git a/extensions/servlet/pom.xml b/extensions/servlet/pom.xml
new file mode 100644
index 0000000..76805c8
--- /dev/null
+++ b/extensions/servlet/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-servlet</artifactId>
+
+  <name>Google Guice - Extensions - Servlet</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.5</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>3.0</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/extensions/servlet/src/com/google/inject/servlet/AbstractServletModuleBinding.java b/extensions/servlet/src/com/google/inject/servlet/AbstractServletModuleBinding.java
new file mode 100644
index 0000000..3566dc1
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/AbstractServletModuleBinding.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import java.util.Map;
+
+/**
+ * Abstract implementation for all servlet module bindings
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+class AbstractServletModuleBinding<T> implements ServletModuleBinding {
+  
+  private final Map<String, String> initParams;
+  private final String pattern;
+  private final T target;
+  private final UriPatternMatcher patternMatcher;
+
+  AbstractServletModuleBinding(Map<String, String> initParams, String pattern, T target,
+      UriPatternMatcher patternMatcher) {
+    this.initParams = initParams;
+    this.pattern = pattern;
+    this.target = target;
+    this.patternMatcher = patternMatcher;
+  }
+
+  public Map<String, String> getInitParams() {
+    return initParams;
+  }
+
+  public String getPattern() {
+    return pattern;
+  }
+
+  protected T getTarget() {
+    return target;
+  }
+
+  public UriPatternType getUriPatternType() {
+    return patternMatcher.getPatternType();
+  }
+  
+  public boolean matchesUri(String uri) {
+    return patternMatcher.matches(uri);
+  }
+
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java b/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java
new file mode 100644
index 0000000..9c473bb
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java
@@ -0,0 +1,143 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.common.collect.Maps;
+import com.google.inject.OutOfScopeException;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpSession;
+
+/**
+ * A wrapper for requests that makes requests immutable, taking a snapshot
+ * of the original request.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+class ContinuingHttpServletRequest extends HttpServletRequestWrapper {
+
+  // We clear out the attributes as they are mutable and not thread-safe.
+  private final Map<String, Object> attributes = Maps.newHashMap();
+  private final Cookie[] cookies;
+
+  public ContinuingHttpServletRequest(HttpServletRequest request) {
+    super(request);
+
+    Cookie[] originalCookies = request.getCookies();
+    if (originalCookies != null) {
+      int numberOfCookies = originalCookies.length;
+      cookies = new Cookie[numberOfCookies];
+      for (int i = 0; i < numberOfCookies; i++) {
+        Cookie originalCookie = originalCookies[i];
+
+        // Snapshot each cookie + freeze.
+        // No snapshot is required if this is a snapshot of a snapshot(!)
+        if (originalCookie instanceof ImmutableCookie) {
+          cookies[i] = originalCookie;
+        } else {
+          cookies[i] = new ImmutableCookie(originalCookie);
+        }
+      }
+    } else {
+      cookies = null;
+    }
+  }
+
+  @Override public HttpSession getSession() {
+    throw new OutOfScopeException("Cannot access the session in a continued request");
+  }
+
+  @Override public HttpSession getSession(boolean create) {
+    throw new UnsupportedOperationException("Cannot access the session in a continued request");
+  }
+
+  @Override public ServletInputStream getInputStream() throws IOException {
+    throw new UnsupportedOperationException("Cannot access raw request on a continued request");
+  }
+
+  @Override public void setAttribute(String name, Object o) {
+    attributes.put(name, o);
+  }
+
+  @Override public void removeAttribute(String name) {
+    attributes.remove(name);
+  }
+
+  @Override public Object getAttribute(String name) {
+    return attributes.get(name);
+  }
+
+  @Override public Cookie[] getCookies() {
+    // NOTE(dhanji): Cookies themselves are mutable. However a ContinuingHttpServletRequest
+    // snapshots the original set of cookies it received and imprisons them in immutable
+    // form. Unfortunately, the cookie array itself is mutable and there is no way for us
+    // to avoid this. At worst, however, mutation effects are restricted within the scope
+    // of a single request. Continued requests are not affected after snapshot time.
+    return cookies;
+  }
+
+  private static final class ImmutableCookie extends Cookie {
+    public ImmutableCookie(Cookie original) {
+      super(original.getName(), original.getValue());
+
+      super.setMaxAge(original.getMaxAge());
+      super.setPath(original.getPath());
+      super.setComment(original.getComment());
+      super.setSecure(original.getSecure());
+      super.setValue(original.getValue());
+      super.setVersion(original.getVersion());
+
+      if (original.getDomain() != null) {
+        super.setDomain(original.getDomain());
+      }
+    }
+
+    @Override public void setComment(String purpose) {
+      throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
+    }
+
+    @Override public void setDomain(String pattern) {
+      throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
+    }
+
+    @Override public void setMaxAge(int expiry) {
+      throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
+    }
+
+    @Override public void setPath(String uri) {
+      throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
+    }
+
+    @Override public void setSecure(boolean flag) {
+      throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
+    }
+
+    @Override public void setValue(String newValue) {
+      throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
+    }
+
+    @Override public void setVersion(int v) {
+      throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/DefaultFilterPipeline.java b/extensions/servlet/src/com/google/inject/servlet/DefaultFilterPipeline.java
new file mode 100644
index 0000000..db32948
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/DefaultFilterPipeline.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import java.io.IOException;
+
+import javax.inject.Inject;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * This default pipeline simply dispatches to web.xml's servlet pipeline.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ * @see com.google.inject.servlet.ManagedFilterPipeline See Also ManagedFilterPipeline.
+ */
+class DefaultFilterPipeline implements FilterPipeline {
+  @Inject DefaultFilterPipeline() {
+  }
+
+  public void initPipeline(ServletContext context) {
+  }
+
+  public void destroyPipeline() {
+  }
+
+  public void dispatch(ServletRequest request, ServletResponse response,
+      FilterChain proceedingFilterChain) throws IOException, ServletException {
+
+    proceedingFilterChain.doFilter(request, response);
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java b/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java
new file mode 100644
index 0000000..b4112cf
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java
@@ -0,0 +1,139 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * A Filter chain impl which basically passes itself to the "current" filter and iterates the chain
+ * on {@code doFilter()}. Modeled on something similar in Apache Tomcat.
+ *
+ * Following this, it attempts to dispatch to guice-servlet's registered servlets using the
+ * ManagedServletPipeline.
+ *
+ * And the end, it proceeds to the web.xml (default) servlet filter chain, if needed.
+ *
+ * @author Dhanji R. Prasanna
+ * @since 1.0
+ */
+class FilterChainInvocation implements FilterChain {
+  
+  private static final Set<String> SERVLET_INTERNAL_METHODS = ImmutableSet.of(
+      FilterChainInvocation.class.getName() + ".doFilter");
+  
+  private final FilterDefinition[] filterDefinitions;
+  private final FilterChain proceedingChain;
+  private final ManagedServletPipeline servletPipeline;
+
+  //state variable tracks current link in filterchain
+  private int index = -1;
+  // whether or not we've caught an exception & cleaned up stack traces
+  private boolean cleanedStacks = false;
+
+  public FilterChainInvocation(FilterDefinition[] filterDefinitions,
+      ManagedServletPipeline servletPipeline, FilterChain proceedingChain) {
+
+    this.filterDefinitions = filterDefinitions;
+    this.servletPipeline = servletPipeline;
+    this.proceedingChain = proceedingChain;
+  }
+
+  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
+      throws IOException, ServletException {
+    GuiceFilter.Context previous = GuiceFilter.localContext.get();
+    HttpServletRequest request = (HttpServletRequest) servletRequest;
+    HttpServletResponse response = (HttpServletResponse) servletResponse;
+    HttpServletRequest originalRequest
+        = (previous != null) ? previous.getOriginalRequest() : request;
+    GuiceFilter.localContext.set(new GuiceFilter.Context(originalRequest, request, response));
+    try {
+      Filter filter = findNextFilter(request);
+      if (filter != null) {
+        // call to the filter, which can either consume the request or
+        // recurse back into this method. (in which case we will go to find the next filter,
+        // or dispatch to the servlet if no more filters are left)
+        filter.doFilter(servletRequest, servletResponse, this);
+      } else {
+        //we've reached the end of the filterchain, let's try to dispatch to a servlet
+        final boolean serviced = servletPipeline.service(servletRequest, servletResponse);
+
+        //dispatch to the normal filter chain only if one of our servlets did not match
+        if (!serviced) {
+          proceedingChain.doFilter(servletRequest, servletResponse);
+        }
+      }
+    } catch (Throwable t) {
+      // Only clean on the first pass through -- one exception deep in a filter
+      // will propogate upward & hit this catch clause multiple times.  We don't
+      // want to iterate through the stack elements for every filter.
+      if (!cleanedStacks) {
+        cleanedStacks = true;
+        pruneStacktrace(t);
+      }
+      Throwables.propagateIfInstanceOf(t, ServletException.class);
+      Throwables.propagateIfInstanceOf(t, IOException.class);
+      throw Throwables.propagate(t);
+    } finally {
+      GuiceFilter.localContext.set(previous);
+    }
+  }
+
+  /**
+   * Iterates over the remaining filter definitions.
+   * Returns the first applicable filter, or null if none apply.
+   */
+  private Filter findNextFilter(HttpServletRequest request) {
+    while (++index < filterDefinitions.length) {
+      Filter filter = filterDefinitions[index].getFilterIfMatching(request);
+      if (filter != null) {
+        return filter;
+      }
+    }
+    return null;
+  }
+  
+  /**
+   * Removes stacktrace elements related to AOP internal mechanics from the
+   * throwable's stack trace and any causes it may have.
+   */
+  private void pruneStacktrace(Throwable throwable) {
+    for (Throwable t = throwable; t != null; t = t.getCause()) {
+      StackTraceElement[] stackTrace = t.getStackTrace();
+      List<StackTraceElement> pruned = Lists.newArrayList();
+      for (StackTraceElement element : stackTrace) {
+        String name = element.getClassName() + "." + element.getMethodName();
+        if (!SERVLET_INTERNAL_METHODS.contains(name)) {
+          pruned.add(element);
+        }
+      }
+      t.setStackTrace(pruned.toArray(new StackTraceElement[pruned.size()]));
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java
new file mode 100644
index 0000000..ff1e5b6
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java
@@ -0,0 +1,167 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.common.collect.Iterators;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Scopes;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * An internal representation of a filter definition against a particular URI pattern.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefinition> {
+  private final String pattern;
+  private final Key<? extends Filter> filterKey;
+  private final UriPatternMatcher patternMatcher;
+  private final Map<String, String> initParams;
+  // set only if this was bound to an instance of a Filter.
+  private final Filter filterInstance;
+
+  // always set after init is called.
+  private final AtomicReference<Filter> filter = new AtomicReference<Filter>();
+
+  public FilterDefinition(String pattern, Key<? extends Filter> filterKey,
+      UriPatternMatcher patternMatcher, Map<String, String> initParams, Filter filterInstance) {
+    this.pattern = pattern;
+    this.filterKey = filterKey;
+    this.patternMatcher = patternMatcher;
+    this.initParams = Collections.unmodifiableMap(new HashMap<String, String>(initParams));
+    this.filterInstance = filterInstance;
+  }
+
+  public FilterDefinition get() {
+    return this;
+  }
+
+  public <B, V> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor,
+      ProviderInstanceBinding<? extends B> binding) {
+    if(visitor instanceof ServletModuleTargetVisitor) {
+      if(filterInstance != null) {
+        return ((ServletModuleTargetVisitor<B, V>)visitor).visit(
+            new InstanceFilterBindingImpl(initParams,
+                pattern,
+                filterInstance,
+                patternMatcher));
+      } else {
+        return ((ServletModuleTargetVisitor<B, V>)visitor).visit(
+            new LinkedFilterBindingImpl(initParams,
+                pattern,
+                filterKey,
+                patternMatcher));
+      }
+    } else {
+      return visitor.visit(binding);
+    }
+  }
+
+  private boolean shouldFilter(String uri) {
+    return uri != null && patternMatcher.matches(uri);
+  }
+
+  public void init(final ServletContext servletContext, Injector injector,
+      Set<Filter> initializedSoFar) throws ServletException {
+
+    // This absolutely must be a singleton, and so is only initialized once.
+    if (!Scopes.isSingleton(injector.getBinding(filterKey))) {
+      throw new ServletException("Filters must be bound as singletons. "
+        + filterKey + " was not bound in singleton scope.");
+    }
+
+    Filter filter = injector.getInstance(filterKey);
+    this.filter.set(filter);
+
+    // Only fire init() if this Singleton filter has not already appeared earlier
+    // in the filter chain.
+    if (initializedSoFar.contains(filter)) {
+      return;
+    }
+
+    //initialize our filter with the configured context params and servlet context
+    filter.init(new FilterConfig() {
+      public String getFilterName() {
+        return filterKey.toString();
+      }
+
+      public ServletContext getServletContext() {
+        return servletContext;
+      }
+
+      public String getInitParameter(String s) {
+        return initParams.get(s);
+      }
+
+      public Enumeration getInitParameterNames() {
+        return Iterators.asEnumeration(initParams.keySet().iterator());
+      }
+    });
+
+    initializedSoFar.add(filter);
+  }
+
+  public void destroy(Set<Filter> destroyedSoFar) {
+    // filters are always singletons
+    Filter reference = filter.get();
+
+    // Do nothing if this Filter was invalid (usually due to not being scoped
+    // properly), or was already destroyed. According to Servlet Spec: it is
+    // "out of service", and does not need to be destroyed.
+    // Also prevent duplicate destroys to the same singleton that may appear
+    // more than once on the filter chain.
+    if (null == reference || destroyedSoFar.contains(reference)) {
+      return;
+    }
+
+    try {
+      reference.destroy();
+    } finally {
+      destroyedSoFar.add(reference);
+    }
+  }
+
+  public Filter getFilterIfMatching(HttpServletRequest request) {
+
+    final String path = ServletUtils.getContextRelativePath(request);
+    if (shouldFilter(path)) {
+      return filter.get();
+    } else {
+      return null;
+    }
+  }
+
+  //VisibleForTesting
+  Filter getFilter() {
+    return filter.get();
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java b/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java
new file mode 100644
index 0000000..985064b
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.inject.ImplementedBy;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * An internal dispatcher for guice-servlet registered servlets and filters.
+ * By default, we assume a Guice 1.0 style servlet module is in play. In other
+ * words, we dispatch directly to the web.xml pipeline after setting up scopes.
+ *
+ * <p>
+ * If on the other hand, {@link ServletModule} is used to register managed
+ * servlets and/or filters, then a different pipeline is bound instead. Which,
+ * after dispatching to Guice-injected filters and servlets continues to the web.xml
+ * pipeline (if necessary).
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+@ImplementedBy(DefaultFilterPipeline.class)
+interface FilterPipeline {
+  void initPipeline(ServletContext context) throws ServletException;
+  void destroyPipeline();
+
+  void dispatch(ServletRequest request, ServletResponse response,
+      FilterChain defaultFilterChain) throws IOException, ServletException;
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java b/extensions/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java
new file mode 100644
index 0000000..4c301ad
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.internal.UniqueAnnotations;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.Filter;
+
+/**
+ * Builds the guice module that binds configured filters, with their
+ * wrapper FilterDefinitions. Is part of the binding EDSL. All Filters
+ * and Servlets are always bound as singletons.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+class FiltersModuleBuilder {
+  
+  private final Binder binder;
+  
+  public FiltersModuleBuilder(Binder binder) {
+    this.binder = binder;
+  }
+
+  public ServletModule.FilterKeyBindingBuilder filter(List<String> patterns) {
+    return new FilterKeyBindingBuilderImpl(patterns, UriPatternType.SERVLET);
+  }
+
+  public ServletModule.FilterKeyBindingBuilder filterRegex(List<String> regexes) {
+    return new FilterKeyBindingBuilderImpl(regexes, UriPatternType.REGEX);
+  }
+
+  //non-static inner class so it can access state of enclosing module class
+  class FilterKeyBindingBuilderImpl implements ServletModule.FilterKeyBindingBuilder {
+    private final List<String> uriPatterns;
+    private final UriPatternType uriPatternType;
+
+    private FilterKeyBindingBuilderImpl(List<String> uriPatterns, UriPatternType uriPatternType) {
+      this.uriPatterns = uriPatterns;
+      this.uriPatternType = uriPatternType;
+    }
+
+    public void through(Class<? extends Filter> filterKey) {
+      through(Key.get(filterKey));
+    }
+
+    public void through(Key<? extends Filter> filterKey) {
+      through(filterKey, new HashMap<String, String>());
+    }
+
+    public void through(Filter filter) {
+      through(filter, new HashMap<String, String>());
+    }
+
+    public void through(Class<? extends Filter> filterKey,
+        Map<String, String> initParams) {
+      
+      // Careful you don't accidentally make this method recursive, thank you IntelliJ IDEA!
+      through(Key.get(filterKey), initParams);
+    }
+
+    public void through(Key<? extends Filter> filterKey,
+        Map<String, String> initParams) {
+      through(filterKey, initParams, null);
+    }
+    
+    private void through(Key<? extends Filter> filterKey,
+        Map<String, String> initParams,
+        Filter filterInstance) {
+      for (String pattern : uriPatterns) {
+        binder.bind(FilterDefinition.class).annotatedWith(UniqueAnnotations.create()).toProvider(
+            new FilterDefinition(pattern, filterKey, UriPatternType.get(uriPatternType, pattern),
+                initParams, filterInstance));
+      }
+    }
+
+    public void through(Filter filter,
+        Map<String, String> initParams) {
+      Key<Filter> filterKey = Key.get(Filter.class, UniqueAnnotations.create());
+      binder.bind(filterKey).toInstance(filter);
+      through(filterKey, initParams, filter);
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
new file mode 100644
index 0000000..ba7a5af
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
@@ -0,0 +1,240 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import com.google.common.base.Throwables;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.OutOfScopeException;
+import com.google.inject.internal.Errors;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.Callable;
+import java.util.logging.Logger;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>
+ * Apply this filter in web.xml above all other filters (typically), to all requests where you plan
+ *  to use servlet scopes. This is also needed in order to dispatch requests to injectable filters
+ *  and servlets:
+ *  <pre>
+ *  &lt;filter&gt;
+ *    &lt;filter-name&gt;guiceFilter&lt;/filter-name&gt;
+ *    &lt;filter-class&gt;<b>com.google.inject.servlet.GuiceFilter</b>&lt;/filter-class&gt;
+ *  &lt;/filter&gt;
+ *
+ *  &lt;filter-mapping&gt;
+ *    &lt;filter-name&gt;guiceFilter&lt;/filter-name&gt;
+ *    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+ *  &lt;/filter-mapping&gt;
+ *  </pre>
+ *
+ * This filter must appear before every filter that makes use of Guice injection or servlet
+ * scopes functionality. Typically, you will only register this filter in web.xml and register
+ * any other filters (and servlets) using a {@link ServletModule}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class GuiceFilter implements Filter {
+  static final ThreadLocal<Context> localContext = new ThreadLocal<Context>();
+  static volatile FilterPipeline pipeline = new DefaultFilterPipeline();
+
+  /**
+   * We allow both the static and dynamic versions of the pipeline to exist.
+   */
+  private final FilterPipeline injectedPipeline;
+
+  /** Used to inject the servlets configured via {@link ServletModule} */
+  static volatile WeakReference<ServletContext> servletContext =
+      new WeakReference<ServletContext>(null);
+
+  private static final String MULTIPLE_INJECTORS_WARNING =
+      "Multiple Servlet injectors detected. This is a warning "
+      + "indicating that you have more than one "
+      + GuiceFilter.class.getSimpleName() + " running "
+      + "in your web application. If this is deliberate, you may safely "
+      + "ignore this message. If this is NOT deliberate however, "
+      + "your application may not work as expected.";
+  
+  private static final Logger LOGGER = Logger.getLogger(GuiceFilter.class.getName());
+
+  public GuiceFilter() {
+    // Use the static FilterPipeline
+    this(null);
+  }
+
+  @Inject GuiceFilter(FilterPipeline filterPipeline) {
+    injectedPipeline = filterPipeline;
+  }
+
+  //VisibleForTesting
+  @Inject
+  static void setPipeline(FilterPipeline pipeline) {
+
+    // This can happen if you create many injectors and they all have their own
+    // servlet module. This is legal, caveat a small warning.
+    if (GuiceFilter.pipeline instanceof ManagedFilterPipeline) {
+      LOGGER.warning(MULTIPLE_INJECTORS_WARNING);
+    }
+
+    // We overwrite the default pipeline
+    GuiceFilter.pipeline = pipeline;
+  }
+
+  //VisibleForTesting
+  static void reset() {
+    pipeline = new DefaultFilterPipeline();
+    localContext.remove();
+  }
+
+  public void doFilter(
+      final ServletRequest servletRequest,
+      final ServletResponse servletResponse,
+      final FilterChain filterChain)
+      throws IOException, ServletException {
+
+    final FilterPipeline filterPipeline = getFilterPipeline();
+
+    Context previous = GuiceFilter.localContext.get();
+    HttpServletRequest request = (HttpServletRequest) servletRequest;
+    HttpServletResponse response = (HttpServletResponse) servletResponse;
+    HttpServletRequest originalRequest
+        = (previous != null) ? previous.getOriginalRequest() : request;
+    try {
+      new Context(originalRequest, request, response).call(new Callable<Void>() {
+        @Override public Void call() throws Exception {
+          //dispatch across the servlet pipeline, ensuring web.xml's filterchain is honored
+          filterPipeline.dispatch(servletRequest, servletResponse, filterChain);
+          return null;
+        }
+      });
+    } catch (IOException e) {
+      throw e;
+    } catch (ServletException e) {
+      throw e;
+    } catch (Exception e) {
+      Throwables.propagate(e);
+    }
+  }
+
+  static HttpServletRequest getOriginalRequest(Key<?> key) {
+    return getContext(key).getOriginalRequest();
+  }
+
+  static HttpServletRequest getRequest(Key<?> key) {
+    return getContext(key).getRequest();
+  }
+
+  static HttpServletResponse getResponse(Key<?> key) {
+    return getContext(key).getResponse();
+  }
+
+  static ServletContext getServletContext() {
+    return servletContext.get();
+  }
+
+  private static Context getContext(Key<?> key) {
+    Context context = localContext.get();
+    if (context == null) {
+      throw new OutOfScopeException("Cannot access scoped [" + Errors.convert(key) 
+          + "]. Either we are not currently inside an HTTP Servlet request, or you may"
+          + " have forgotten to apply " + GuiceFilter.class.getName()
+          + " as a servlet filter for this request.");
+    }
+    return context;
+  }
+
+  static class Context {
+    final HttpServletRequest originalRequest;
+    final HttpServletRequest request;
+    final HttpServletResponse response;
+
+    Context(HttpServletRequest originalRequest, HttpServletRequest request,
+        HttpServletResponse response) {
+      this.originalRequest = originalRequest;
+      this.request = request;
+      this.response = response;
+    }
+
+    HttpServletRequest getOriginalRequest() {
+      return originalRequest;
+    }
+
+    HttpServletRequest getRequest() {
+      return request;
+    }
+
+    HttpServletResponse getResponse() {
+      return response;
+    }
+
+    // Synchronized to prevent two threads from using the same request
+    // scope concurrently.
+    synchronized <T> T call(Callable<T> callable) throws Exception {
+      Context previous = localContext.get();
+      localContext.set(this);
+      try {
+        return callable.call();
+      } finally {
+        localContext.set(previous);
+      }
+    }
+  }
+
+  public void init(FilterConfig filterConfig) throws ServletException {
+    final ServletContext servletContext = filterConfig.getServletContext();
+
+    // Store servlet context in a weakreference, for injection
+    GuiceFilter.servletContext = new WeakReference<ServletContext>(servletContext);
+
+    // In the default pipeline, this is a noop. However, if replaced
+    // by a managed pipeline, a lazy init will be triggered the first time
+    // dispatch occurs.
+    FilterPipeline filterPipeline = getFilterPipeline();
+    filterPipeline.initPipeline(servletContext);
+  }
+
+  public void destroy() {
+
+    try {
+      // Destroy all registered filters & servlets in that order
+      FilterPipeline filterPipeline = getFilterPipeline();
+      filterPipeline.destroyPipeline();
+
+    } finally {
+      reset();
+      servletContext.clear();
+    }
+  }
+
+  private FilterPipeline getFilterPipeline() {
+    // Prefer the injected pipeline, but fall back on the static one for web.xml users.
+    return (null != injectedPipeline) ? injectedPipeline : pipeline;
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/GuiceServletContextListener.java b/extensions/servlet/src/com/google/inject/servlet/GuiceServletContextListener.java
new file mode 100644
index 0000000..ffc189b
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/GuiceServletContextListener.java
@@ -0,0 +1,63 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import com.google.inject.Injector;
+
+import java.lang.ref.WeakReference;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+/**
+ * As of Guice 2.0 you can still use (your subclasses of) {@code GuiceServletContextListener}
+ * class as a logical place to create and configure your injector. This will ensure the injector
+ * is created when the web application is deployed.
+ * 
+ * @author Kevin Bourrillion (kevinb@google.com)
+ * @since 2.0
+ */
+public abstract class GuiceServletContextListener
+    implements ServletContextListener {
+
+  static final String INJECTOR_NAME = Injector.class.getName();
+
+  public void contextInitialized(ServletContextEvent servletContextEvent) {
+    final ServletContext servletContext = servletContextEvent.getServletContext();
+
+    // Set the Servletcontext early for those people who are using this class.
+    // NOTE(dhanji): This use of the servletContext is deprecated.
+    GuiceFilter.servletContext = new WeakReference<ServletContext>(servletContext);
+
+    Injector injector = getInjector();
+    injector.getInstance(InternalServletModule.BackwardsCompatibleServletContextProvider.class)
+        .set(servletContext);
+    servletContext.setAttribute(INJECTOR_NAME, injector);
+  }
+
+  public void contextDestroyed(ServletContextEvent servletContextEvent) {
+    ServletContext servletContext = servletContextEvent.getServletContext();
+    servletContext.removeAttribute(INJECTOR_NAME);
+  }
+
+  /**
+   * Override this method to create (or otherwise obtain a reference to) your
+   * injector.
+   */
+  protected abstract Injector getInjector();
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBinding.java b/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBinding.java
new file mode 100644
index 0000000..e0cca0f
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBinding.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import javax.servlet.Filter;
+
+/**
+ * A binding to a single instance of a filter. 
+ *
+ * @author sameb@google.com
+ * @since 3.0
+ */
+public interface InstanceFilterBinding extends ServletModuleBinding {
+
+  /** Returns the filter instance that will be used. */
+  Filter getFilterInstance();
+
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBindingImpl.java b/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBindingImpl.java
new file mode 100644
index 0000000..57b5efb
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBindingImpl.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.common.base.Objects;
+
+import java.util.Map;
+
+import javax.servlet.Filter;
+
+/**
+ * Default implementation of InstanceFilterBinding.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+class InstanceFilterBindingImpl extends AbstractServletModuleBinding<Filter> implements
+    InstanceFilterBinding {
+
+  InstanceFilterBindingImpl(Map<String, String> initParams, String pattern,
+      Filter target, UriPatternMatcher patternMatcher) {
+    super(initParams, pattern, target, patternMatcher);
+  }
+
+  public Filter getFilterInstance() {
+    return getTarget();
+  }
+  
+  @Override public String toString() {
+    return Objects.toStringHelper(InstanceFilterBinding.class)
+      .add("pattern", getPattern())
+      .add("initParams", getInitParams())
+      .add("uriPatternType", getUriPatternType())
+      .add("filterInstance", getFilterInstance())
+      .toString();
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/InstanceServletBinding.java b/extensions/servlet/src/com/google/inject/servlet/InstanceServletBinding.java
new file mode 100644
index 0000000..d466cfc
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/InstanceServletBinding.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import javax.servlet.http.HttpServlet;
+
+/**
+ * A binding to a single instance of a servlet. 
+ *
+ * @author sameb@google.com
+ * @since 3.0
+ */
+public interface InstanceServletBinding extends ServletModuleBinding {
+
+  /** Returns the servlet instance that will be used. */
+  HttpServlet getServletInstance();
+
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/InstanceServletBindingImpl.java b/extensions/servlet/src/com/google/inject/servlet/InstanceServletBindingImpl.java
new file mode 100644
index 0000000..6e275cb
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/InstanceServletBindingImpl.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.common.base.Objects;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServlet;
+
+/**
+ * Default implementation of InstanceServletBinding.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+class InstanceServletBindingImpl extends AbstractServletModuleBinding<HttpServlet> implements
+    InstanceServletBinding {
+
+  InstanceServletBindingImpl(Map<String, String> initParams, String pattern,
+      HttpServlet target, UriPatternMatcher patternMatcher) {
+    super(initParams, pattern, target, patternMatcher);
+  }
+
+  public HttpServlet getServletInstance() {
+    return getTarget();
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(InstanceServletBinding.class)
+      .add("pattern", getPattern())
+      .add("initParams", getInitParams())
+      .add("uriPatternType", getUriPatternType())
+      .add("servletInstance", getServletInstance())
+      .toString();
+  }
+  
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java b/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java
new file mode 100644
index 0000000..4b234ba
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java
@@ -0,0 +1,133 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import static com.google.inject.servlet.ServletScopes.REQUEST;
+import static com.google.inject.servlet.ServletScopes.SESSION;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * This is a left-factoring of all ServletModules installed in the system.
+ * In other words, this module contains the bindings common to all ServletModules,
+ * and is bound exactly once per injector.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+final class InternalServletModule extends AbstractModule {
+
+  /**
+   * Special Provider that tries to obtain an injected servlet context, specific
+   * to the current injector, failing which, it falls back to the static singleton
+   * instance that is available in the legacy Guice Servlet.
+   */
+  @Singleton
+  static class BackwardsCompatibleServletContextProvider implements Provider<ServletContext> {
+    private ServletContext injectedServletContext;
+
+    @Inject BackwardsCompatibleServletContextProvider() {}
+
+    // This setter is called by the GuiceServletContextListener
+    void set(ServletContext injectedServletContext) {
+      this.injectedServletContext = injectedServletContext;
+    }
+
+    public ServletContext get() {
+      if (null != injectedServletContext) {
+        return injectedServletContext;
+      }
+
+      Logger.getLogger(InternalServletModule.class.getName())
+          .warning("You are attempting to use a deprecated API (specifically,"
+          + " attempting to @Inject ServletContext inside an eagerly created"
+          + " singleton. While we allow this for backwards compatibility, be"
+          + " warned that this MAY have unexpected behavior if you have more"
+          + " than one injector (with ServletModule) running in the same JVM."
+          + " Please consult the Guice documentation at"
+          + " https://github.com/google/guice/wiki/Servlets for more"
+          + " information.");
+      return GuiceFilter.getServletContext();
+    }
+  }
+
+  @Override
+  protected void configure() {
+    bindScope(RequestScoped.class, REQUEST);
+    bindScope(SessionScoped.class, SESSION);
+    bind(ServletRequest.class).to(HttpServletRequest.class);
+    bind(ServletResponse.class).to(HttpServletResponse.class);
+
+    // inject the pipeline into GuiceFilter so it can route requests correctly
+    // Unfortunate staticness... =(
+    // NOTE(dhanji): This is maintained for legacy purposes.
+    requestStaticInjection(GuiceFilter.class);
+
+    bind(ManagedFilterPipeline.class);
+    bind(ManagedServletPipeline.class);
+    bind(FilterPipeline.class).to(ManagedFilterPipeline.class).asEagerSingleton();
+
+    bind(ServletContext.class).toProvider(BackwardsCompatibleServletContextProvider.class);
+    bind(BackwardsCompatibleServletContextProvider.class);
+  }
+
+  @Provides @Singleton @ScopingOnly GuiceFilter provideScopingOnlyGuiceFilter() {
+    return new GuiceFilter(new DefaultFilterPipeline());
+  }
+
+  @Provides @RequestScoped HttpServletRequest provideHttpServletRequest() {
+    return GuiceFilter.getRequest(Key.get(HttpServletRequest.class));
+  }
+
+  @Provides @RequestScoped HttpServletResponse provideHttpServletResponse() {
+    return GuiceFilter.getResponse(Key.get(HttpServletResponse.class));
+  }
+
+  @Provides HttpSession provideHttpSession() {
+    return GuiceFilter.getRequest(Key.get(HttpSession.class)).getSession();
+  }
+
+  @SuppressWarnings("unchecked") // defined by getParameterMap()
+  @Provides @RequestScoped @RequestParameters Map<String, String[]> provideRequestParameters(
+      ServletRequest req) {
+    return req.getParameterMap();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    // Is only ever installed internally, so we don't need to check state.
+    return o instanceof InternalServletModule;
+  }
+
+  @Override
+  public int hashCode() {
+    return InternalServletModule.class.hashCode();
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBinding.java b/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBinding.java
new file mode 100644
index 0000000..a30bdc3
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBinding.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.inject.Key;
+
+import javax.servlet.Filter;
+
+/**
+ * A linked binding to a filter. 
+ *
+ * @author sameb@google.com
+ * @since 3.0
+ */
+public interface LinkedFilterBinding extends ServletModuleBinding {
+
+  /** Returns the key used to lookup the filter instance. */
+  Key<? extends Filter> getLinkedKey();
+
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBindingImpl.java b/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBindingImpl.java
new file mode 100644
index 0000000..5b87ca9
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBindingImpl.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.common.base.Objects;
+import com.google.inject.Key;
+
+import java.util.Map;
+
+import javax.servlet.Filter;
+
+/**
+ * Default implementation of LinkedFilterBinding.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+class LinkedFilterBindingImpl extends AbstractServletModuleBinding<Key<? extends Filter>>
+    implements LinkedFilterBinding {
+
+  LinkedFilterBindingImpl(Map<String, String> initParams, String pattern,
+      Key<? extends Filter> target, UriPatternMatcher patternMatcher) {
+    super(initParams, pattern, target, patternMatcher);
+  }
+
+  public Key<? extends Filter> getLinkedKey() {
+    return getTarget();
+  }
+  
+  @Override public String toString() {
+    return Objects.toStringHelper(LinkedFilterBinding.class)
+      .add("pattern", getPattern())
+      .add("initParams", getInitParams())
+      .add("uriPatternType", getUriPatternType())
+      .add("linkedFilterKey", getLinkedKey())
+      .toString();
+  }
+  
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/LinkedServletBinding.java b/extensions/servlet/src/com/google/inject/servlet/LinkedServletBinding.java
new file mode 100644
index 0000000..335dd1d
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/LinkedServletBinding.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.inject.Key;
+
+import javax.servlet.http.HttpServlet;
+
+/**
+ * A linked binding to a servlet. 
+ *
+ * @author sameb@google.com
+ * @since 3.0
+ */
+public interface LinkedServletBinding extends ServletModuleBinding {
+
+  /** Returns the key used to lookup the servlet instance. */
+  Key<? extends HttpServlet> getLinkedKey();
+
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/LinkedServletBindingImpl.java b/extensions/servlet/src/com/google/inject/servlet/LinkedServletBindingImpl.java
new file mode 100644
index 0000000..8e73735
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/LinkedServletBindingImpl.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.common.base.Objects;
+import com.google.inject.Key;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServlet;
+
+/**
+ * Default implementation of LinkedServletBinding.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+class LinkedServletBindingImpl extends AbstractServletModuleBinding<Key<? extends HttpServlet>>
+    implements LinkedServletBinding {
+
+  LinkedServletBindingImpl(Map<String, String> initParams, String pattern,
+      Key<? extends HttpServlet> target, UriPatternMatcher patternMatcher) {
+    super(initParams, pattern, target, patternMatcher);
+  }
+
+  public Key<? extends HttpServlet> getLinkedKey() {
+    return getTarget();
+  }
+
+  @Override public String toString() {
+    return Objects.toStringHelper(LinkedServletBinding.class)
+      .add("pattern", getPattern())
+      .add("initParams", getInitParams())
+      .add("uriPatternType", getUriPatternType())
+      .add("linkedServletKey", getLinkedKey())
+      .toString();
+  }
+  
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java b/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java
new file mode 100644
index 0000000..538e10a
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.TypeLiteral;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+/**
+ * Central routing/dispatch class handles lifecycle of managed filters, and delegates to the servlet
+ * pipeline.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+@Singleton
+class ManagedFilterPipeline implements FilterPipeline{
+  private final FilterDefinition[] filterDefinitions;
+  private final ManagedServletPipeline servletPipeline;
+  private final Provider<ServletContext> servletContext;
+
+  //Unfortunately, we need the injector itself in order to create filters + servlets
+  private final Injector injector;
+
+  //Guards a DCL, so needs to be volatile
+  private volatile boolean initialized = false;
+  private static final TypeLiteral<FilterDefinition> FILTER_DEFS =
+      TypeLiteral.get(FilterDefinition.class);
+
+  @Inject
+  public ManagedFilterPipeline(Injector injector, ManagedServletPipeline servletPipeline,
+      Provider<ServletContext> servletContext) {
+    this.injector = injector;
+    this.servletPipeline = servletPipeline;
+    this.servletContext = servletContext;
+
+    this.filterDefinitions = collectFilterDefinitions(injector);
+  }
+
+  /**
+   * Introspects the injector and collects all instances of bound {@code List<FilterDefinition>}
+   * into a master list.
+   * 
+   * We have a guarantee that {@link com.google.inject.Injector#getBindings()} returns a map
+   * that preserves insertion order in entry-set iterators.
+   */
+  private FilterDefinition[] collectFilterDefinitions(Injector injector) {
+    List<FilterDefinition> filterDefinitions = Lists.newArrayList();
+    for (Binding<FilterDefinition> entry : injector.findBindingsByType(FILTER_DEFS)) {
+      filterDefinitions.add(entry.getProvider().get());
+    }
+    
+    // Copy to a fixed-size array for speed of iteration.
+    return filterDefinitions.toArray(new FilterDefinition[filterDefinitions.size()]);
+  }
+
+  public synchronized void initPipeline(ServletContext servletContext)
+      throws ServletException {
+
+    //double-checked lock, prevents duplicate initialization
+    if (initialized)
+      return;
+
+    // Used to prevent duplicate initialization.
+    Set<Filter> initializedSoFar = Sets.newIdentityHashSet();
+
+    for (FilterDefinition filterDefinition : filterDefinitions) {
+      filterDefinition.init(servletContext, injector, initializedSoFar);
+    }
+
+    //next, initialize servlets...
+    servletPipeline.init(servletContext, injector);
+
+    //everything was ok...
+    initialized = true;
+  }
+
+  public void dispatch(ServletRequest request, ServletResponse response,
+      FilterChain proceedingFilterChain) throws IOException, ServletException {
+
+    //lazy init of filter pipeline (OK by the servlet specification). This is needed
+    //in order for us not to force users to create a GuiceServletContextListener subclass.
+    if (!initialized) {
+      initPipeline(servletContext.get());
+    }
+
+    //obtain the servlet pipeline to dispatch against
+    new FilterChainInvocation(filterDefinitions, servletPipeline, proceedingFilterChain)
+        .doFilter(withDispatcher(request, servletPipeline), response);
+
+  }
+
+  /**
+   * Used to create an proxy that dispatches either to the guice-servlet pipeline or the regular
+   * pipeline based on uri-path match. This proxy also provides minimal forwarding support.
+   *
+   * We cannot forward from a web.xml Servlet/JSP to a guice-servlet (because the filter pipeline
+   * is not called again). However, we can wrap requests with our own dispatcher to forward the
+   * *other* way. web.xml Servlets/JSPs can forward to themselves as per normal.
+   *
+   * This is not a problem cuz we intend for people to migrate from web.xml to guice-servlet,
+   * incrementally, but not the other way around (which, we should actively discourage).
+   */
+  @SuppressWarnings({ "JavaDoc", "deprecation" })
+  private ServletRequest withDispatcher(ServletRequest servletRequest,
+      final ManagedServletPipeline servletPipeline) {
+
+    // don't wrap the request if there are no servlets mapped. This prevents us from inserting our
+    // wrapper unless it's actually going to be used. This is necessary for compatibility for apps
+    // that downcast their HttpServletRequests to a concrete implementation.
+    if (!servletPipeline.hasServletsMapped()) {
+      return servletRequest;
+    }
+
+    HttpServletRequest request = (HttpServletRequest) servletRequest;
+    //noinspection OverlyComplexAnonymousInnerClass
+    return new HttpServletRequestWrapper(request) {
+
+      @Override
+      public RequestDispatcher getRequestDispatcher(String path) {
+        final RequestDispatcher dispatcher = servletPipeline.getRequestDispatcher(path);
+
+        return (null != dispatcher) ? dispatcher : super.getRequestDispatcher(path);
+      }
+    };
+  }
+
+  public void destroyPipeline() {
+    //destroy servlets first
+    servletPipeline.destroy();
+
+    //go down chain and destroy all our filters
+    Set<Filter> destroyedSoFar = Sets.newIdentityHashSet();
+    for (FilterDefinition filterDefinition : filterDefinitions) {
+      filterDefinition.destroy(destroyedSoFar);
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java b/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java
new file mode 100644
index 0000000..455551a
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java
@@ -0,0 +1,213 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+import com.google.inject.TypeLiteral;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+/**
+ * A wrapping dispatcher for servlets, in much the same way as {@link ManagedFilterPipeline} is for
+ * filters.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+@Singleton
+class ManagedServletPipeline {
+  private final ServletDefinition[] servletDefinitions;
+  private static final TypeLiteral<ServletDefinition> SERVLET_DEFS =
+      TypeLiteral.get(ServletDefinition.class);
+
+  @Inject
+  public ManagedServletPipeline(Injector injector) {
+    this.servletDefinitions = collectServletDefinitions(injector);
+  }
+
+  boolean hasServletsMapped() {
+    return servletDefinitions.length > 0;
+  }
+
+  /**
+   * Introspects the injector and collects all instances of bound {@code List<ServletDefinition>}
+   * into a master list.
+   *
+   * We have a guarantee that {@link com.google.inject.Injector#getBindings()} returns a map
+   * that preserves insertion order in entry-set iterators.
+   */
+  private ServletDefinition[] collectServletDefinitions(Injector injector) {
+    List<ServletDefinition> servletDefinitions = Lists.newArrayList();
+    for (Binding<ServletDefinition> entry : injector.findBindingsByType(SERVLET_DEFS)) {
+        servletDefinitions.add(entry.getProvider().get());
+    }
+
+    // Copy to a fixed size array for speed.
+    return servletDefinitions.toArray(new ServletDefinition[servletDefinitions.size()]);
+  }
+
+  public void init(ServletContext servletContext, Injector injector) throws ServletException {
+    Set<HttpServlet> initializedSoFar = Sets.newIdentityHashSet();
+
+    for (ServletDefinition servletDefinition : servletDefinitions) {
+      servletDefinition.init(servletContext, injector, initializedSoFar);
+    }
+  }
+
+  public boolean service(ServletRequest request, ServletResponse response)
+      throws IOException, ServletException {
+
+    //stop at the first matching servlet and service
+    for (ServletDefinition servletDefinition : servletDefinitions) {
+      if (servletDefinition.service(request, response)) {
+        return true;
+      }
+    }
+
+    //there was no match...
+    return false;
+  }
+
+  public void destroy() {
+    Set<HttpServlet> destroyedSoFar = Sets.newIdentityHashSet();
+    for (ServletDefinition servletDefinition : servletDefinitions) {
+      servletDefinition.destroy(destroyedSoFar);
+    }
+  }
+
+  /**
+   * @return Returns a request dispatcher wrapped with a servlet mapped to
+   * the given path or null if no mapping was found.
+   */
+  RequestDispatcher getRequestDispatcher(String path) {
+    final String newRequestUri = path;
+
+    // TODO(dhanji): check servlet spec to see if the following is legal or not.
+    // Need to strip query string if requested...
+
+    for (final ServletDefinition servletDefinition : servletDefinitions) {
+      if (servletDefinition.shouldServe(path)) {
+        return new RequestDispatcher() {
+          public void forward(ServletRequest servletRequest, ServletResponse servletResponse)
+              throws ServletException, IOException {
+            Preconditions.checkState(!servletResponse.isCommitted(),
+                "Response has been committed--you can only call forward before"
+                + " committing the response (hint: don't flush buffers)");
+
+            // clear buffer before forwarding
+            servletResponse.resetBuffer();
+
+            ServletRequest requestToProcess;
+            if (servletRequest instanceof HttpServletRequest) {
+               requestToProcess = wrapRequest((HttpServletRequest)servletRequest, newRequestUri);
+            } else {
+              // This should never happen, but instead of throwing an exception
+              // we will allow a happy case pass thru for maximum tolerance to
+              // legacy (and internal) code.
+              requestToProcess = servletRequest;
+            }
+
+            // now dispatch to the servlet
+            doServiceImpl(servletDefinition, requestToProcess, servletResponse);
+          }
+
+          public void include(ServletRequest servletRequest, ServletResponse servletResponse)
+              throws ServletException, IOException {
+            // route to the target servlet
+            doServiceImpl(servletDefinition, servletRequest, servletResponse);
+          }
+
+          private void doServiceImpl(ServletDefinition servletDefinition, ServletRequest servletRequest,
+              ServletResponse servletResponse) throws ServletException, IOException {
+            servletRequest.setAttribute(REQUEST_DISPATCHER_REQUEST, Boolean.TRUE);
+
+            try {
+              servletDefinition.doService(servletRequest, servletResponse);
+            } finally {
+              servletRequest.removeAttribute(REQUEST_DISPATCHER_REQUEST);
+            }
+          }
+        };
+      }
+    }
+
+    //otherwise, can't process
+    return null;
+  }
+
+  // visible for testing
+  static HttpServletRequest wrapRequest(HttpServletRequest request, String newUri) {
+    return new RequestDispatcherRequestWrapper(request, newUri);
+  }
+
+  /**
+   * A Marker constant attribute that when present in the request indicates to Guice servlet that
+   * this request has been generated by a request dispatcher rather than the servlet pipeline.
+   * In accordance with section 8.4.2 of the Servlet 2.4 specification.
+   */
+  public static final String REQUEST_DISPATCHER_REQUEST = "javax.servlet.forward.servlet_path";
+
+  private static class RequestDispatcherRequestWrapper extends HttpServletRequestWrapper {
+    private final String newRequestUri;
+
+    public RequestDispatcherRequestWrapper(HttpServletRequest servletRequest, String newRequestUri) {
+      super(servletRequest);
+      this.newRequestUri = newRequestUri;
+    }
+
+    @Override
+    public String getRequestURI() {
+      return newRequestUri;
+    }
+
+    @Override
+    public StringBuffer getRequestURL() {
+      StringBuffer url = new StringBuffer();
+      String scheme = getScheme();
+      int port = getServerPort();
+
+      url.append(scheme);
+      url.append("://");
+      url.append(getServerName());
+      // port might be -1 in some cases (see java.net.URL.getPort)
+      if (port > 0 &&
+          (("http".equals(scheme) && (port != 80)) ||
+           ("https".equals(scheme) && (port != 443)))) {
+        url.append(':');
+        url.append(port);
+      }
+      url.append(getRequestURI());
+
+      return (url);
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/RequestParameters.java b/extensions/servlet/src/com/google/inject/servlet/RequestParameters.java
new file mode 100644
index 0000000..ca5bbc3
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/RequestParameters.java
@@ -0,0 +1,36 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Apply this to field or parameters of type {@code Map<String, String[]>}
+ * when you want the HTTP request parameter map to be injected.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@BindingAnnotation
+public @interface RequestParameters {}
diff --git a/extensions/servlet/src/com/google/inject/servlet/RequestScoped.java b/extensions/servlet/src/com/google/inject/servlet/RequestScoped.java
new file mode 100644
index 0000000..38f9cff
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/RequestScoped.java
@@ -0,0 +1,34 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import com.google.inject.ScopeAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Apply this to implementation classes when you want one instance per request.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@ScopeAnnotation
+public @interface RequestScoped {}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ScopingException.java b/extensions/servlet/src/com/google/inject/servlet/ScopingException.java
new file mode 100644
index 0000000..1513959
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ScopingException.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (C) 2012 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.inject.servlet;
+
+/**
+ * Exception thrown when there was a failure entering request scope.
+ *
+ * @author Chris Nokleberg
+ * @since 4.0
+ */
+public final class ScopingException extends IllegalStateException {
+  public ScopingException(String message) {
+    super(message);
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ScopingOnly.java b/extensions/servlet/src/com/google/inject/servlet/ScopingOnly.java
new file mode 100644
index 0000000..d828d75
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ScopingOnly.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.servlet;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates a {@link GuiceFilter} that provides scope functionality, but
+ * doesn't dispatch to {@link ServletModule} bound servlets or filters.
+ *
+ * @author iqshum@google.com (Isaac Shum)
+ * @since 4.0
+ */
+@Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@BindingAnnotation
+public @interface ScopingOnly {}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
new file mode 100644
index 0000000..11328ed
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
@@ -0,0 +1,300 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
+
+import com.google.common.collect.Iterators;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Scopes;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * An internal representation of a servlet definition mapped to a particular URI pattern. Also
+ * performs the request dispatch to that servlet. How nice and OO =)
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+class ServletDefinition implements ProviderWithExtensionVisitor<ServletDefinition> {
+  private final String pattern;
+  private final Key<? extends HttpServlet> servletKey;
+  private final UriPatternMatcher patternMatcher;
+  private final Map<String, String> initParams;
+  // set only if this was bound using a servlet instance.
+  private final HttpServlet servletInstance;
+
+  //always set in init, our servlet is always presumed to be a singleton
+  private final AtomicReference<HttpServlet> httpServlet = new AtomicReference<HttpServlet>();
+
+  public ServletDefinition(String pattern, Key<? extends HttpServlet> servletKey,
+      UriPatternMatcher patternMatcher, Map<String, String> initParams, HttpServlet servletInstance) {
+    this.pattern = pattern;
+    this.servletKey = servletKey;
+    this.patternMatcher = patternMatcher;
+    this.initParams = Collections.unmodifiableMap(new HashMap<String, String>(initParams));
+    this.servletInstance = servletInstance;
+  }
+
+  public ServletDefinition get() {
+    return this;
+  }
+
+  public <B, V> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor,
+      ProviderInstanceBinding<? extends B> binding) {
+    if(visitor instanceof ServletModuleTargetVisitor) {
+      if(servletInstance != null) {
+        return ((ServletModuleTargetVisitor<B, V>)visitor).visit(
+            new InstanceServletBindingImpl(initParams,
+                pattern,
+                servletInstance,
+                patternMatcher));
+      } else {
+        return ((ServletModuleTargetVisitor<B, V>)visitor).visit(
+            new LinkedServletBindingImpl(initParams,
+                pattern,
+                servletKey,
+                patternMatcher));
+      }
+    } else {
+      return visitor.visit(binding);
+    }
+  }
+
+  boolean shouldServe(String uri) {
+    return uri != null && patternMatcher.matches(uri);
+  }
+
+  public void init(final ServletContext servletContext, Injector injector,
+      Set<HttpServlet> initializedSoFar) throws ServletException {
+
+    // This absolutely must be a singleton, and so is only initialized once.
+    if (!Scopes.isSingleton(injector.getBinding(servletKey))) {
+      throw new ServletException("Servlets must be bound as singletons. "
+        + servletKey + " was not bound in singleton scope.");
+    }
+
+    HttpServlet httpServlet = injector.getInstance(servletKey);
+    this.httpServlet.set(httpServlet);
+
+    // Only fire init() if we have not appeared before in the filter chain.
+    if (initializedSoFar.contains(httpServlet)) {
+      return;
+    }
+
+    //initialize our servlet with the configured context params and servlet context
+    httpServlet.init(new ServletConfig() {
+      public String getServletName() {
+        return servletKey.toString();
+      }
+
+      public ServletContext getServletContext() {
+        return servletContext;
+      }
+
+      public String getInitParameter(String s) {
+        return initParams.get(s);
+      }
+
+      public Enumeration getInitParameterNames() {
+        return Iterators.asEnumeration(initParams.keySet().iterator());
+      }
+    });
+
+    // Mark as initialized.
+    initializedSoFar.add(httpServlet);
+  }
+
+  public void destroy(Set<HttpServlet> destroyedSoFar) {
+    HttpServlet reference = httpServlet.get();
+
+    // Do nothing if this Servlet was invalid (usually due to not being scoped
+    // properly). According to Servlet Spec: it is "out of service", and does not
+    // need to be destroyed.
+    // Also prevent duplicate destroys to the same singleton that may appear
+    // more than once on the filter chain.
+    if (null == reference || destroyedSoFar.contains(reference)) {
+      return;
+    }
+
+    try {
+      reference.destroy();
+    } finally {
+      destroyedSoFar.add(reference);
+    }
+  }
+
+  /**
+   * Wrapper around the service chain to ensure a servlet is servicing what it must and provides it
+   * with a wrapped request.
+   *
+   * @return Returns true if this servlet triggered for the given request. Or false if
+   *          guice-servlet should continue dispatching down the servlet pipeline.
+   *
+   * @throws IOException If thrown by underlying servlet
+   * @throws ServletException If thrown by underlying servlet
+   */
+  public boolean service(ServletRequest servletRequest,
+      ServletResponse servletResponse) throws IOException, ServletException {
+
+    final HttpServletRequest request = (HttpServletRequest) servletRequest;
+    final String path = ServletUtils.getContextRelativePath(request);
+
+    final boolean serve = shouldServe(path);
+
+    //invocations of the chain end at the first matched servlet
+    if (serve) {
+      doService(servletRequest, servletResponse);
+    }
+
+    //return false if no servlet matched (so we can proceed down to the web.xml servlets)
+    return serve;
+  }
+
+  /**
+   * Utility that delegates to the actual service method of the servlet wrapped with a contextual
+   * request (i.e. with correctly computed path info).
+   *
+   * We need to suppress deprecation coz we use HttpServletRequestWrapper, which implements
+   * deprecated API for backwards compatibility.
+   */
+  void doService(final ServletRequest servletRequest, ServletResponse servletResponse)
+      throws ServletException, IOException {
+
+    HttpServletRequest request = new HttpServletRequestWrapper(
+        (HttpServletRequest) servletRequest) {
+      private boolean pathComputed;
+      private String path;
+
+      private boolean pathInfoComputed;
+      private String pathInfo;
+
+      @Override
+      public String getPathInfo() {
+        if (!isPathInfoComputed()) {
+          String servletPath = getServletPath();
+          int servletPathLength = servletPath.length();
+          String requestUri = getRequestURI();
+          pathInfo = requestUri.substring(getContextPath().length()).replaceAll("[/]{2,}", "/");
+          // See: https://github.com/google/guice/issues/372
+          if (pathInfo.startsWith(servletPath)) {
+            pathInfo = pathInfo.substring(servletPathLength);
+            // Corner case: when servlet path & request path match exactly (without trailing '/'),
+            // then pathinfo is null.
+            if (pathInfo.isEmpty() && servletPathLength > 0) {
+              pathInfo = null;
+            } else {
+              try {
+                pathInfo = new URI(pathInfo).getPath();
+              } catch (URISyntaxException e) {
+                // ugh, just leave it alone then
+              }
+            }
+          } else {
+            pathInfo = null; // we know nothing additional about the URI.
+          }
+          pathInfoComputed = true;
+        }
+
+        return pathInfo;
+      }
+
+      // NOTE(dhanji): These two are a bit of a hack to help ensure that request dispatcher-sent
+      // requests don't use the same path info that was memoized for the original request.
+      // NOTE(iqshum): I don't think this is possible, since the dispatcher-sent request would
+      // perform its own wrapping.
+      private boolean isPathInfoComputed() {
+        return pathInfoComputed && servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST) == null;
+      }
+
+      private boolean isPathComputed() {
+        return pathComputed && servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST) == null;
+      }
+
+      @Override
+      public String getServletPath() {
+        return computePath();
+      }
+
+      @Override
+      public String getPathTranslated() {
+        final String info = getPathInfo();
+
+        return (null == info) ? null : getRealPath(info);
+      }
+
+      // Memoizer pattern.
+      private String computePath() {
+        if (!isPathComputed()) {
+          String servletPath = super.getServletPath();
+          path = patternMatcher.extractPath(servletPath);
+          pathComputed = true;
+
+          if (null == path) {
+            path = servletPath;
+          }
+        }
+
+        return path;
+      }
+    };
+
+    doServiceImpl(request, (HttpServletResponse) servletResponse);
+  }
+
+  private void doServiceImpl(HttpServletRequest request, HttpServletResponse response)
+      throws ServletException, IOException {
+    GuiceFilter.Context previous = GuiceFilter.localContext.get();
+    HttpServletRequest originalRequest
+        = (previous != null) ? previous.getOriginalRequest() : request;
+    GuiceFilter.localContext.set(new GuiceFilter.Context(originalRequest, request, response));
+    try {
+      httpServlet.get().service(request, response);
+    } finally {
+      GuiceFilter.localContext.set(previous);
+    }
+  }
+
+  String getKey() {
+    return servletKey.toString();
+  }
+
+  String getPattern() {
+    return pattern;
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletModule.java b/extensions/servlet/src/com/google/inject/servlet/ServletModule.java
new file mode 100644
index 0000000..c85e7ad
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletModule.java
@@ -0,0 +1,325 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.AbstractModule;
+import com.google.inject.Key;
+
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServlet;
+
+/**
+ * Configures the servlet scopes and creates bindings for the servlet API
+ * objects so you can inject the request, response, session, etc.
+ *
+ * <p>
+ * You should subclass this module to register servlets and
+ * filters in the {@link #configureServlets()} method.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class ServletModule extends AbstractModule {
+
+  @Override
+  protected final void configure() {
+    checkState(filtersModuleBuilder == null, "Re-entry is not allowed.");
+    checkState(servletsModuleBuilder == null, "Re-entry is not allowed.");
+    filtersModuleBuilder = new FiltersModuleBuilder(binder());
+    servletsModuleBuilder = new ServletsModuleBuilder(binder());
+    try {
+      // Install common bindings (skipped if already installed).
+      install(new InternalServletModule());
+  
+      // Install local filter and servlet bindings.
+      configureServlets();
+    } finally {
+      filtersModuleBuilder = null;
+      servletsModuleBuilder = null;
+    }
+  }
+
+  /**
+   * <h3>Servlet Mapping EDSL</h3>
+   *
+   * <p> Part of the EDSL builder language for configuring servlets
+   * and filters with guice-servlet. Think of this as an in-code replacement for web.xml.
+   * Filters and servlets are configured here using simple java method calls. Here is a typical
+   * example of registering a filter when creating your Guice injector:
+   *
+   * <pre>
+   *   Guice.createInjector(..., new ServletModule() {
+   *
+   *     {@literal @}Override
+   *     protected void configureServlets() {
+   *       <b>serve("*.html").with(MyServlet.class)</b>
+   *     }
+   *   }
+   * </pre>
+   *
+   * This registers a servlet (subclass of {@code HttpServlet}) called {@code MyServlet} to service
+   * any web pages ending in {@code .html}. You can also use a path-style syntax to register
+   * servlets:
+   *
+   * <pre>
+   *       <b>serve("/my/*").with(MyServlet.class)</b>
+   * </pre>
+   *
+   * Every servlet (or filter) is required to be a singleton. If you cannot annotate the class
+   * directly, you should add a separate {@code bind(..).in(Singleton.class)} rule elsewhere in
+   * your module. Mapping a servlet that is bound under any other scope is an error.
+   *
+   * <p>
+   * <h4>Dispatch Order</h4>
+   * You are free to register as many servlets and filters as you like this way. They will
+   * be compared and dispatched in the order in which the filter methods are called:
+   *
+   * <pre>
+   *
+   *   Guice.createInjector(..., new ServletModule() {
+   *
+   *     {@literal @}Override
+   *     protected void configureServlets() {
+   *       filter("/*").through(MyFilter.class);
+   *       filter("*.css").through(MyCssFilter.class);
+   *       filter("*.jpg").through(new MyJpgFilter());
+   *       // etc..
+   *
+   *       serve("*.html").with(MyServlet.class);
+   *       serve("/my/*").with(MyServlet.class);
+   *       serve("*.jpg").with(new MyServlet());
+   *       // etc..
+   *      }
+   *    }
+   * </pre>
+   * This will traverse down the list of rules in lexical order. For example, a url
+   *  "{@code /my/file.js}" (after it runs through the matching filters) will first
+   *  be compared against the servlet mapping:
+   * 
+   * <pre>
+   *       serve("*.html").with(MyServlet.class);
+   * </pre>
+   * And failing that, it will descend to the next servlet mapping:
+   *
+   * <pre>
+   *       serve("/my/*").with(MyServlet.class);
+   * </pre>
+   *
+   * Since this rule matches, Guice Servlet will dispatch to {@code MyServlet}. These
+   * two mapping rules can also be written in more compact form using varargs syntax:
+   *
+   * <pre>
+   *       serve(<b>"*.html", "/my/*"</b>).with(MyServlet.class);
+   * </pre>
+   * 
+   * This way you can map several URI patterns to the same servlet. A similar syntax is
+   * also available for filter mappings.
+   *
+   * <p>
+   * <h4>Regular Expressions</h4>
+   * You can also map servlets (or filters) to URIs using regular expressions:
+   * <pre>
+   *    <b>serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)</b>
+   * </pre>
+   *
+   * This will map any URI containing the text "ajax" in it to {@code MyAjaxServlet}. Such as:
+   * <ul>
+   * <li>http://www.google.com/ajax.html</li>
+   * <li>http://www.google.com/content/ajax/index</li>
+   * <li>http://www.google.com/it/is_totally_ajaxian</li>
+   * </ul>
+   *
+   *
+   * <h3>Initialization Parameters</h3>
+   *
+   * Servlets (and filters) allow you to pass in init params
+   * using the {@code <init-param>} tag in web.xml. You can similarly pass in parameters to
+   * Servlets and filters registered in Guice-servlet using a {@link java.util.Map} of parameter
+   * name/value pairs. For example, to initialize {@code MyServlet} with two parameters
+   * ({@code name="Dhanji", site="google.com"}) you could write:
+   *
+   * <pre>
+   *  Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
+   *  params.put("name", "Dhanji");
+   *  params.put("site", "google.com");
+   *
+   *  ...
+   *      serve("/*").with(MyServlet.class, <b>params</b>)
+   * </pre>
+   *
+   * <p>
+   * <h3>Binding Keys</h3>
+   *
+   * You can also bind keys rather than classes. This lets you hide
+   * implementations with package-local visbility and expose them using
+   * only a Guice module and an annotation:
+   *
+   * <pre>
+   *  ...
+   *      filter("/*").through(<b>Key.get(Filter.class, Fave.class)</b>);
+   * </pre>
+   *
+   * Where {@code Filter.class} refers to the Servlet API interface and {@code Fave.class} is a
+   * custom binding annotation. Elsewhere (in one of your own modules) you can bind this
+   * filter's implementation:
+   *
+   * <pre>
+   *   bind(Filter.class)<b>.annotatedWith(Fave.class)</b>.to(MyFilterImpl.class);
+   * </pre>
+   *
+   * See {@link com.google.inject.Binder} for more information on binding syntax.
+   *
+   * <p>
+   * <h3>Multiple Modules</h3>
+   *
+   * It is sometimes useful to capture servlet and filter mappings from multiple different
+   * modules. This is essential if you want to package and offer drop-in Guice plugins that
+   * provide servlet functionality.
+   *
+   * <p>
+   * Guice Servlet allows you to register several instances of {@code ServletModule} to your
+   * injector. The order in which these modules are installed determines the dispatch order
+   * of filters and the precedence order of servlets. For example, if you had two servlet modules,
+   * {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped
+   * to the same URI pattern, {@code "/*"}:
+   *
+   * <p>
+   * In {@code RpcModule}:
+   * <pre>
+   *     filter("/*").through(RpcFilter.class);
+   * </pre>
+   *
+   * In {@code WebServiceModule}:
+   * <pre>
+   *     filter("/*").through(WebServiceFilter.class);
+   * </pre>
+   *
+   * Then the order in which these filters are dispatched is determined by the order in which
+   * the modules are installed:
+   *
+   * <pre>
+   *   <b>install(new WebServiceModule());</b>
+   *   install(new RpcModule());
+   * </pre>
+   *
+   * In the case shown above {@code WebServiceFilter} will run first.
+   * 
+   * @since 2.0
+   */
+  protected void configureServlets() {
+  }
+
+
+  private FiltersModuleBuilder filtersModuleBuilder;
+  private ServletsModuleBuilder servletsModuleBuilder;
+
+  private FiltersModuleBuilder getFiltersModuleBuilder() {
+    checkState(filtersModuleBuilder != null,
+        "This method can only be used inside configureServlets()");
+    return filtersModuleBuilder;
+  }
+
+  private ServletsModuleBuilder getServletModuleBuilder() {
+    checkState(servletsModuleBuilder != null,
+        "This method can only be used inside configureServlets()");
+    return servletsModuleBuilder;
+  }
+
+  /**
+   * @param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
+   * @since 2.0
+   */
+  protected final FilterKeyBindingBuilder filter(String urlPattern, String... morePatterns) {
+    return getFiltersModuleBuilder()
+        .filter(ImmutableList.<String>builder().add(urlPattern).add(morePatterns).build());
+  }
+
+  /**
+   * @param regex Any Java-style regular expression.
+   * @since 2.0
+   */
+  protected final FilterKeyBindingBuilder filterRegex(String regex, String... regexes) {
+    return getFiltersModuleBuilder()
+        .filterRegex(ImmutableList.<String>builder().add(regex).add(regexes).build());
+  }
+
+  /**
+   * @param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
+   * @since 2.0
+   */
+  protected final ServletKeyBindingBuilder serve(String urlPattern, String... morePatterns) {
+    return getServletModuleBuilder()
+        .serve(ImmutableList.<String>builder().add(urlPattern).add(morePatterns).build());
+  }
+
+  /**
+   * @param regex Any Java-style regular expression.
+   * @since 2.0
+   */
+  protected final ServletKeyBindingBuilder serveRegex(String regex, String... regexes) {
+    return getServletModuleBuilder()
+        .serveRegex(ImmutableList.<String>builder().add(regex).add(regexes).build());
+  }
+
+  /**
+   * This method only works if you are using the {@linkplain GuiceServletContextListener} to
+   * create your injector. Otherwise, it returns null.
+   * @return The current servlet context.
+   * @since 3.0
+   */
+  protected final ServletContext getServletContext() {
+    return GuiceFilter.getServletContext();
+  }
+
+  /**
+   * See the EDSL examples at {@link ServletModule#configureServlets()}
+   *
+   * @since 2.0
+   */
+  public static interface FilterKeyBindingBuilder {
+    void through(Class<? extends Filter> filterKey);
+    void through(Key<? extends Filter> filterKey);
+    /** @since 3.0 */
+    void through(Filter filter);
+    void through(Class<? extends Filter> filterKey, Map<String, String> initParams);
+    void through(Key<? extends Filter> filterKey, Map<String, String> initParams);
+    /** @since 3.0 */
+    void through(Filter filter, Map<String, String> initParams);
+  }
+
+  /**
+   * See the EDSL examples at {@link ServletModule#configureServlets()}
+   *
+   * @since 2.0
+   */
+  public static interface ServletKeyBindingBuilder {
+    void with(Class<? extends HttpServlet> servletKey);
+    void with(Key<? extends HttpServlet> servletKey);
+    /** @since 3.0 */
+    void with(HttpServlet servlet);
+    void with(Class<? extends HttpServlet> servletKey, Map<String, String> initParams);
+    void with(Key<? extends HttpServlet> servletKey, Map<String, String> initParams);
+    /** @since 3.0 */
+    void with(HttpServlet servlet, Map<String, String> initParams);
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletModuleBinding.java b/extensions/servlet/src/com/google/inject/servlet/ServletModuleBinding.java
new file mode 100644
index 0000000..7895744
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletModuleBinding.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import java.util.Map;
+
+/**
+ * A binding created by {@link ServletModule}.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ * @since 3.0
+ */
+public interface ServletModuleBinding {
+
+  /** Returns the pattern type that this binding was created with. */
+  UriPatternType getUriPatternType();
+
+  /** Returns the pattern used to match against the binding. */
+  String getPattern();
+
+  /** Returns any context params supplied when creating the binding. */
+  Map<String, String> getInitParams();
+  
+  /** Returns true if the given URI will match this binding. */
+  boolean matchesUri(String uri);
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletModuleTargetVisitor.java b/extensions/servlet/src/com/google/inject/servlet/ServletModuleTargetVisitor.java
new file mode 100644
index 0000000..fade33d
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletModuleTargetVisitor.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder;
+import com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder;
+import com.google.inject.spi.BindingTargetVisitor;
+
+import javax.servlet.Filter;
+import javax.servlet.http.HttpServlet;
+
+/**
+ * A visitor for the servlet extension.
+ * 
+ * If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ * {@link ServletModule} will be visited through this interface.
+ * 
+ * @since 3.0
+ * @author sameb@google.com (Sam Berlin)
+ */
+public interface ServletModuleTargetVisitor<T, V> extends BindingTargetVisitor<T, V> {
+
+  /**
+   * Visits a filter binding created by {@link ServletModule#filter}, where
+   * {@link FilterKeyBindingBuilder#through} is called with a Class or Key.
+   * 
+   * If multiple patterns were specified, this will be called multiple times.
+   */
+  V visit(LinkedFilterBinding binding);
+
+  /**
+   * Visits a filter binding created by {@link ServletModule#filter} where
+   * {@link FilterKeyBindingBuilder#through} is called with a {@link Filter}.
+   * 
+   * If multiple patterns were specified, this will be called multiple times. 
+   */
+  V visit(InstanceFilterBinding binding);
+
+  /**
+   * Visits a servlet binding created by {@link ServletModule#serve} where
+   * {@link ServletKeyBindingBuilder#with}, is called with a Class or Key.
+   * 
+   * If multiple patterns were specified, this will be called multiple times.
+   */
+  V visit(LinkedServletBinding binding);
+
+  /**
+   * Visits a servlet binding created by {@link ServletModule#serve} where 
+   * {@link ServletKeyBindingBuilder#with}, is called with an {@link HttpServlet}.
+   * 
+   * If multiple patterns were specified, this will be called multiple times.
+   */
+  V visit(InstanceServletBinding binding);
+}
\ No newline at end of file
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java b/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java
new file mode 100644
index 0000000..54c120e
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java
@@ -0,0 +1,387 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Maps.EntryTransformer;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.OutOfScopeException;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.Scopes;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * Servlet scopes.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ServletScopes {
+
+  private ServletScopes() {}
+
+  /**
+   * A threadlocal scope map for non-http request scopes. The {@link #REQUEST}
+   * scope falls back to this scope map if no http request is available, and
+   * requires {@link #scopeRequest} to be called as an alternative.
+   */
+  private static final ThreadLocal<Context> requestScopeContext
+      = new ThreadLocal<Context>();
+
+  /** A sentinel attribute value representing null. */
+  enum NullObject { INSTANCE }
+
+  /**
+   * HTTP servlet request scope.
+   */
+  public static final Scope REQUEST = new Scope() {
+    public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator) {
+      return new Provider<T>() {
+
+        /** Keys bound in request-scope which are handled directly by GuiceFilter. */
+        private final ImmutableSet<Key<?>> REQUEST_CONTEXT_KEYS = ImmutableSet.of(
+                Key.get(HttpServletRequest.class),
+                Key.get(HttpServletResponse.class),
+                new Key<Map<String, String[]>>(RequestParameters.class) {});
+
+        public T get() {
+          // Check if the alternate request scope should be used, if no HTTP
+          // request is in progress.
+          if (null == GuiceFilter.localContext.get()) {
+
+            // NOTE(dhanji): We don't need to synchronize on the scope map
+            // unlike the HTTP request because we're the only ones who have
+            // a reference to it, and it is only available via a threadlocal.
+            Context context = requestScopeContext.get();
+            if (null != context) {
+              @SuppressWarnings("unchecked")
+              T t = (T) context.map.get(key);
+
+              // Accounts for @Nullable providers.
+              if (NullObject.INSTANCE == t) {
+                return null;
+              }
+
+              if (t == null) {
+                t = creator.get();
+                if (!Scopes.isCircularProxy(t)) {
+                  // Store a sentinel for provider-given null values.
+                  context.map.put(key, t != null ? t : NullObject.INSTANCE);
+                }
+              }
+
+              return t;
+            } // else: fall into normal HTTP request scope and out of scope
+              // exception is thrown.
+          }
+
+          // Always synchronize and get/set attributes on the underlying request
+          // object since Filters may wrap the request and change the value of
+          // {@code GuiceFilter.getRequest()}.
+          //
+          // This _correctly_ throws up if the thread is out of scope.
+          HttpServletRequest request = GuiceFilter.getOriginalRequest(key);
+          if (REQUEST_CONTEXT_KEYS.contains(key)) {
+            // Don't store these keys as attributes, since they are handled by
+            // GuiceFilter itself.
+            return creator.get();
+          }
+          String name = key.toString();
+          synchronized (request) {
+            Object obj = request.getAttribute(name);
+            if (NullObject.INSTANCE == obj) {
+              return null;
+            }
+            @SuppressWarnings("unchecked")
+            T t = (T) obj;
+            if (t == null) {
+              t = creator.get();
+              if (!Scopes.isCircularProxy(t)) {
+                request.setAttribute(name, (t != null) ? t : NullObject.INSTANCE);
+              }
+            }
+            return t;
+          }
+        }
+
+        @Override
+        public String toString() {
+          return String.format("%s[%s]", creator, REQUEST);
+        }
+      };
+    }
+
+    @Override
+    public String toString() {
+      return "ServletScopes.REQUEST";
+    }
+  };
+
+  /**
+   * HTTP session scope.
+   */
+  public static final Scope SESSION = new Scope() {
+    public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator) {
+      final String name = key.toString();
+      return new Provider<T>() {
+        public T get() {
+          HttpSession session = GuiceFilter.getRequest(key).getSession();
+          synchronized (session) {
+            Object obj = session.getAttribute(name);
+            if (NullObject.INSTANCE == obj) {
+              return null;
+            }
+            @SuppressWarnings("unchecked")
+            T t = (T) obj;
+            if (t == null) {
+              t = creator.get();
+              if (!Scopes.isCircularProxy(t)) {
+                session.setAttribute(name, (t != null) ? t : NullObject.INSTANCE);
+              }
+            }
+            return t;
+          }
+        }
+        @Override
+        public String toString() {
+          return String.format("%s[%s]", creator, SESSION);
+        }
+      };
+    }
+
+    @Override
+    public String toString() {
+      return "ServletScopes.SESSION";
+    }
+  };
+
+  /**
+   * Wraps the given callable in a contextual callable that "continues" the
+   * HTTP request in another thread. This acts as a way of transporting
+   * request context data from the request processing thread to to worker
+   * threads.
+   * <p>
+   * There are some limitations:
+   * <ul>
+   *   <li>Derived objects (i.e. anything marked @RequestScoped will not be
+   *      transported.</li>
+   *   <li>State changes to the HttpServletRequest after this method is called
+   *      will not be seen in the continued thread.</li>
+   *   <li>Only the HttpServletRequest, ServletContext and request parameter
+   *      map are available in the continued thread. The response and session
+   *      are not available.</li>
+   * </ul>
+   *
+   * <p>The returned callable will throw a {@link ScopingException} when called
+   * if the HTTP request scope is still active on the current thread.
+   *
+   * @param callable code to be executed in another thread, which depends on
+   *     the request scope.
+   * @param seedMap the initial set of scoped instances for Guice to seed the
+   *     request scope with.  To seed a key with null, use {@code null} as
+   *     the value.
+   * @return a callable that will invoke the given callable, making the request
+   *     context available to it.
+   * @throws OutOfScopeException if this method is called from a non-request
+   *     thread, or if the request has completed.
+   * 
+   * @since 3.0
+   */
+  public static <T> Callable<T> continueRequest(final Callable<T> callable,
+      final Map<Key<?>, Object> seedMap) {
+    Preconditions.checkArgument(null != seedMap,
+        "Seed map cannot be null, try passing in Collections.emptyMap() instead.");
+
+    // Snapshot the seed map and add all the instances to our continuing HTTP request.
+    final ContinuingHttpServletRequest continuingRequest =
+        new ContinuingHttpServletRequest(
+            GuiceFilter.getRequest(Key.get(HttpServletRequest.class)));
+    for (Map.Entry<Key<?>, Object> entry : seedMap.entrySet()) {
+      Object value = validateAndCanonicalizeValue(entry.getKey(), entry.getValue());
+      continuingRequest.setAttribute(entry.getKey().toString(), value);
+    }
+
+    return new Callable<T>() {
+      public T call() throws Exception {
+        checkScopingState(null == GuiceFilter.localContext.get(),
+            "Cannot continue request in the same thread as a HTTP request!");
+        return new GuiceFilter.Context(continuingRequest, continuingRequest, null)
+            .call(callable);
+      }
+    };
+  }
+
+  /**
+   * Wraps the given callable in a contextual callable that "transfers" the
+   * request to another thread. This acts as a way of transporting
+   * request context data from the current thread to a future thread.
+   *
+   * <p>As opposed to {@link #continueRequest}, this method propagates all
+   * existing scoped objects. The primary use case is in server implementations
+   * where you can detach the request processing thread while waiting for data,
+   * and reattach to a different thread to finish processing at a later time.
+   *
+   * <p>Because request-scoped objects are not typically thread-safe, the
+   * callable returned by this method must not be run on a different thread
+   * until the current request scope has terminated. The returned callable will
+   * block until the current thread has released the request scope.
+   *
+   * @param callable code to be executed in another thread, which depends on
+   *     the request scope.
+   * @return a callable that will invoke the given callable, making the request
+   *     context available to it.
+   * @throws OutOfScopeException if this method is called from a non-request
+   *     thread, or if the request has completed.
+   * @since 4.0
+   */
+  public static <T> Callable<T> transferRequest(Callable<T> callable) {
+    return (GuiceFilter.localContext.get() != null)
+        ? transferHttpRequest(callable)
+        : transferNonHttpRequest(callable);
+  }
+
+  private static <T> Callable<T> transferHttpRequest(final Callable<T> callable) {
+    final GuiceFilter.Context context = GuiceFilter.localContext.get();
+    if (context == null) {
+      throw new OutOfScopeException("Not in a request scope");
+    }
+    return new Callable<T>() {
+      public T call() throws Exception {
+        return context.call(callable);
+      }
+    };
+  }
+
+  private static <T> Callable<T> transferNonHttpRequest(final Callable<T> callable) {
+    final Context context = requestScopeContext.get();
+    if (context == null) {
+      throw new OutOfScopeException("Not in a request scope");
+    }
+    return new Callable<T>() {
+      public T call() throws Exception {
+        return context.call(callable);
+      }
+    };
+  }
+
+  /**
+   * Returns true if {@code binding} is request-scoped. If the binding is a
+   * {@link com.google.inject.spi.LinkedKeyBinding linked key binding} and
+   * belongs to an injector (i. e. it was retrieved via
+   * {@link Injector#getBinding Injector.getBinding()}), then this method will
+   * also return true if the target binding is request-scoped.
+   *
+   * @since 4.0
+   */
+  public static boolean isRequestScoped(Binding<?> binding) {
+    return Scopes.isScoped(binding, ServletScopes.REQUEST, RequestScoped.class);
+  }
+
+  /**
+   * Scopes the given callable inside a request scope. This is not the same
+   * as the HTTP request scope, but is used if no HTTP request scope is in
+   * progress. In this way, keys can be scoped as @RequestScoped and exist
+   * in non-HTTP requests (for example: RPC requests) as well as in HTTP
+   * request threads.
+   *
+   * <p>The returned callable will throw a {@link ScopingException} when called
+   * if there is a request scope already active on the current thread.
+   *
+   * @param callable code to be executed which depends on the request scope.
+   *     Typically in another thread, but not necessarily so.
+   * @param seedMap the initial set of scoped instances for Guice to seed the
+   *     request scope with.  To seed a key with null, use {@code null} as
+   *     the value.
+   * @return a callable that when called will run inside the a request scope
+   *     that exposes the instances in the {@code seedMap} as scoped keys.
+   * @since 3.0
+   */
+  public static <T> Callable<T> scopeRequest(final Callable<T> callable,
+      Map<Key<?>, Object> seedMap) {
+    Preconditions.checkArgument(null != seedMap,
+        "Seed map cannot be null, try passing in Collections.emptyMap() instead.");
+
+    // Copy the seed values into our local scope map.
+    final Context context = new Context();
+    Map<Key<?>, Object> validatedAndCanonicalizedMap =
+        Maps.transformEntries(seedMap, new EntryTransformer<Key<?>, Object, Object>() {
+          @Override public Object transformEntry(Key<?> key, Object value) {
+            return validateAndCanonicalizeValue(key, value);
+          }
+        });
+    context.map.putAll(validatedAndCanonicalizedMap);
+
+    return new Callable<T>() {
+      public T call() throws Exception {
+        checkScopingState(null == GuiceFilter.localContext.get(),
+            "An HTTP request is already in progress, cannot scope a new request in this thread.");
+        checkScopingState(null == requestScopeContext.get(),
+            "A request scope is already in progress, cannot scope a new request in this thread.");
+        return context.call(callable);
+      }
+    };
+  }
+
+  /**
+   * Validates the key and object, ensuring the value matches the key type, and
+   * canonicalizing null objects to the null sentinel.
+   */
+  private static Object validateAndCanonicalizeValue(Key<?> key, Object object) {
+    if (object == null || object == NullObject.INSTANCE) {
+      return NullObject.INSTANCE;
+    }
+
+    if (!key.getTypeLiteral().getRawType().isInstance(object)) {
+      throw new IllegalArgumentException("Value[" + object + "] of type["
+          + object.getClass().getName() + "] is not compatible with key[" + key + "]");
+    }
+
+    return object;
+  }
+
+  private static class Context {
+    final Map<Key, Object> map = Maps.newHashMap();
+
+    // Synchronized to prevent two threads from using the same request
+    // scope concurrently.
+    synchronized <T> T call(Callable<T> callable) throws Exception {
+      Context previous = requestScopeContext.get();
+      requestScopeContext.set(this);
+      try {
+        return callable.call();
+      } finally {
+        requestScopeContext.set(previous);
+      }
+    }
+  }
+
+  private static void checkScopingState(boolean condition, String msg) {
+    if (!condition) {
+      throw new ScopingException(msg);
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletUtils.java b/extensions/servlet/src/com/google/inject/servlet/ServletUtils.java
new file mode 100644
index 0000000..88ecd31
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletUtils.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2012 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.inject.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Some servlet utility methods.
+ *
+ * @author ntang@google.com (Michael Tang)
+ */
+final class ServletUtils {
+  private ServletUtils() {
+    // private to prevent instantiation.
+  }
+
+  /**
+   * Gets the context path relative path of the URI. Returns the path of the
+   * resource relative to the context path for a request's URI, or null if no
+   * path can be extracted.
+   */
+  // @Nullable
+  public static String getContextRelativePath(
+      // @Nullable
+      final HttpServletRequest request) {
+    if (request != null) {
+      String contextPath = request.getContextPath();
+      String requestURI = request.getRequestURI();
+      if (contextPath.length() < requestURI.length()) {
+        return requestURI.substring(contextPath.length());
+      } else if (requestURI != null && requestURI.trim().length() > 0 &&
+          contextPath.length() == requestURI.length()) {
+        return "/";
+      }
+    }
+    return null;
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java b/extensions/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java
new file mode 100644
index 0000000..79f2d0b
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.internal.UniqueAnnotations;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServlet;
+
+/**
+ * Builds the guice module that binds configured servlets, with their
+ * wrapper ServletDefinitions. Is part of the binding EDSL. Very similar to
+ * {@link com.google.inject.servlet.FiltersModuleBuilder}.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail.com)
+ */
+class ServletsModuleBuilder {
+  
+  private final Set<String> servletUris = Sets.newHashSet();
+  private final Binder binder;
+  
+  public ServletsModuleBuilder(Binder binder) {
+    this.binder = binder;
+  }
+
+  //the first level of the EDSL--
+  public ServletModule.ServletKeyBindingBuilder serve(List<String> urlPatterns) {
+    return new ServletKeyBindingBuilderImpl(urlPatterns, UriPatternType.SERVLET);
+  }
+
+  public ServletModule.ServletKeyBindingBuilder serveRegex(List<String> regexes) {
+    return new ServletKeyBindingBuilderImpl(regexes, UriPatternType.REGEX);
+  }
+
+  //non-static inner class so it can access state of enclosing module class
+  class ServletKeyBindingBuilderImpl implements ServletModule.ServletKeyBindingBuilder {
+    private final List<String> uriPatterns;
+    private final UriPatternType uriPatternType;
+
+    private ServletKeyBindingBuilderImpl(List<String> uriPatterns, UriPatternType uriPatternType) {
+      this.uriPatterns = uriPatterns;
+      this.uriPatternType = uriPatternType;
+    }
+
+    public void with(Class<? extends HttpServlet> servletKey) {
+      with(Key.get(servletKey));
+    }
+
+    public void with(Key<? extends HttpServlet> servletKey) {
+      with(servletKey, new HashMap<String, String>());
+    }
+
+    public void with(HttpServlet servlet) {
+      with(servlet, new HashMap<String, String>());
+    }
+
+    public void with(Class<? extends HttpServlet> servletKey,
+        Map<String, String> initParams) {
+      with(Key.get(servletKey), initParams);
+    }
+
+    public void with(Key<? extends HttpServlet> servletKey,
+        Map<String, String> initParams) {
+      with(servletKey, initParams, null);
+    }
+
+    private void with(Key<? extends HttpServlet> servletKey, Map<String, String> initParams,
+        HttpServlet servletInstance) {
+      for (String pattern : uriPatterns) {
+        // Ensure two servlets aren't bound to the same pattern.
+        if (!servletUris.add(pattern)) {
+          binder.addError("More than one servlet was mapped to the same URI pattern: " + pattern);
+        } else {
+          binder.bind(Key.get(ServletDefinition.class, UniqueAnnotations.create())).toProvider(
+              new ServletDefinition(pattern, servletKey, UriPatternType
+                  .get(uriPatternType, pattern), initParams, servletInstance));
+        }
+      }
+    }
+
+    public void with(HttpServlet servlet,
+        Map<String, String> initParams) {
+      Key<HttpServlet> servletKey = Key.get(HttpServlet.class, UniqueAnnotations.create());
+      binder.bind(servletKey).toInstance(servlet);
+      with(servletKey, initParams, servlet);
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/SessionScoped.java b/extensions/servlet/src/com/google/inject/servlet/SessionScoped.java
new file mode 100644
index 0000000..5b61e26
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/SessionScoped.java
@@ -0,0 +1,35 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import com.google.inject.ScopeAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Apply this to implementation classes when you want one instance per session.
+ *
+ * @see com.google.inject.Scopes#SINGLETON
+ * @author crazybob@google.com (Bob Lee)
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@ScopeAnnotation
+public @interface SessionScoped {}
diff --git a/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java b/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java
new file mode 100644
index 0000000..d8bac74
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+/**
+ * A general interface for matching a URI against a URI pattern. Guice-servlet provides regex and
+ * servlet-style pattern matching out of the box.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+interface UriPatternMatcher {
+  /**
+   * @param uri A "contextual" (i.e. relative) Request URI, *not* a complete one.
+   * @return Returns true if the uri matches the pattern.
+   */
+  boolean matches(String uri);
+
+  /**
+   * @param pattern The Path that this service pattern can match against.
+   * @return Returns a canonical servlet path from this pattern. For instance, if the pattern is
+   *         {@code /home/*} then the path extracted will be {@code /home}. Each pattern matcher
+   *         implementation must decide and publish what a canonical path represents.
+   *
+   *         NOTE(dhanji): This method returns null for the regex pattern matcher.
+   */
+  String extractPath(String pattern);
+  
+  /** Returns the type of pattern this is. */
+  UriPatternType getPatternType();
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java b/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java
new file mode 100644
index 0000000..80d6aea
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java
@@ -0,0 +1,148 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * An enumeration of the available URI-pattern matching styles
+ * 
+ * @since 3.0
+ */
+public enum UriPatternType {
+  SERVLET, REGEX;
+
+  static UriPatternMatcher get(UriPatternType type, String pattern) {
+    switch (type) {
+      case SERVLET:
+        return new ServletStyleUriPatternMatcher(pattern);
+      case REGEX:
+        return new RegexUriPatternMatcher(pattern);
+      default:
+        return null;
+    }
+  }
+
+  private static String getUri(String uri) {
+    // Strip out the query, if it existed in the URI.  See issue 379.
+    int queryIdx = uri.indexOf('?');
+    if (queryIdx != -1) {
+      uri = uri.substring(0, queryIdx);
+    }
+    return uri;
+  }
+
+  /**
+   * Matches URIs using the pattern grammar of the Servlet API and web.xml.
+   *
+   * @author dhanji@gmail.com (Dhanji R. Prasanna)
+   */
+  private static class ServletStyleUriPatternMatcher implements UriPatternMatcher {
+    private final String pattern;
+    private final Kind patternKind;
+
+    private static enum Kind { PREFIX, SUFFIX, LITERAL, }
+
+    public ServletStyleUriPatternMatcher(String pattern) {
+      if (pattern.startsWith("*")) {
+        this.pattern = pattern.substring(1);
+        this.patternKind = Kind.PREFIX;
+      } else if (pattern.endsWith("*")) {
+        this.pattern = pattern.substring(0, pattern.length() - 1);
+        this.patternKind = Kind.SUFFIX;
+      } else {
+        this.pattern = pattern;
+        this.patternKind = Kind.LITERAL;
+      }
+    }
+
+    public boolean matches(String uri) {
+      if (null == uri) {
+        return false;
+      }
+
+      uri = getUri(uri);
+      if (patternKind == Kind.PREFIX) {
+        return uri.endsWith(pattern);
+      } else if (patternKind == Kind.SUFFIX) {
+        return uri.startsWith(pattern);
+      }
+
+      //else treat as a literal
+      return pattern.equals(uri);
+    }
+
+    public String extractPath(String path) {
+      if (patternKind == Kind.PREFIX) {
+        return null;
+      } else if (patternKind == Kind.SUFFIX) {
+        String extract = pattern;
+
+        //trim the trailing '/'
+        if (extract.endsWith("/")) {
+          extract = extract.substring(0, extract.length() - 1);
+        }
+
+        return extract;
+      }
+
+      //else treat as literal
+      return path;
+    }
+    
+    public UriPatternType getPatternType() {
+      return UriPatternType.SERVLET;
+    }
+  }
+
+  /**
+   * Matches URIs using a regular expression.
+   *
+   * @author dhanji@gmail.com (Dhanji R. Prasanna)
+   */
+  private static class RegexUriPatternMatcher implements UriPatternMatcher {
+    private final Pattern pattern;
+
+    public RegexUriPatternMatcher(String pattern) {
+      this.pattern = Pattern.compile(pattern);
+    }
+
+    public boolean matches(String uri) {
+      return null != uri && this.pattern.matcher(getUri(uri)).matches();
+    }
+
+    public String extractPath(String path) {
+      Matcher matcher = pattern.matcher(path);
+      if (matcher.matches() && matcher.groupCount() >= 1) {
+
+        // Try to capture the everything before the regex begins to match
+        // the path. This is a rough approximation to try and get parity
+        // with the servlet style mapping where the path is a capture of
+        // the URI before the wildcard.
+        int end = matcher.start(1);
+        if (end < path.length()) {
+          return path.substring(0, end);
+        }
+      }
+      return null;
+    }
+    
+    public UriPatternType getPatternType() {
+      return UriPatternType.REGEX;
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/package-info.java b/extensions/servlet/src/com/google/inject/servlet/package-info.java
new file mode 100644
index 0000000..53f2746
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/package-info.java
@@ -0,0 +1,25 @@
+/**
+ * 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.
+ */
+
+/**
+ * Servlet API scopes, bindings and registration; this extension requires {@code
+ * guice-servlet.jar}.
+ *
+ * <p>Apply {@link com.google.inject.servlet.GuiceFilter} to any servlets which will use the servlet
+ * scopes. Install {@link com.google.inject.servlet.ServletModule} into your {@link
+ * com.google.inject.Injector} to install everything at once.
+ */
+package com.google.inject.servlet;
diff --git a/extensions/servlet/test/com/google/inject/servlet/AllTests.java b/extensions/servlet/test/com/google/inject/servlet/AllTests.java
new file mode 100644
index 0000000..a80c398
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/AllTests.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class AllTests {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+
+    // Filter tests.
+    suite.addTestSuite(EdslTest.class);
+    suite.addTestSuite(FilterDefinitionTest.class);
+    suite.addTestSuite(FilterDispatchIntegrationTest.class);
+    suite.addTestSuite(FilterPipelineTest.class);
+
+    // Servlet + integration tests.
+    suite.addTestSuite(ServletModuleTest.class);
+    suite.addTestSuite(ServletTest.class);
+    suite.addTestSuite(ServletDefinitionTest.class);
+    suite.addTestSuite(ServletDefinitionPathsTest.class);
+    suite.addTestSuite(ServletPipelineRequestDispatcherTest.class);
+    suite.addTestSuite(ServletDispatchIntegrationTest.class);
+    suite.addTestSuite(InvalidScopeBindingTest.class);
+    suite.addTestSuite(ContinuingHttpServletRequestTest.class);
+
+    // Varargs URL mapping tests.
+    suite.addTestSuite(VarargsFilterDispatchIntegrationTest.class);
+    suite.addTestSuite(VarargsServletDispatchIntegrationTest.class);
+
+    // Multiple modules tests.
+    suite.addTestSuite(MultiModuleDispatchIntegrationTest.class);
+
+    // Extension SPI tests.
+    suite.addTestSuite(ExtensionSpiTest.class);
+
+    suite.addTestSuite(UriPatternTypeTest.class);
+
+    return suite;
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ContextPathTest.java b/extensions/servlet/test/com/google/inject/servlet/ContextPathTest.java
new file mode 100644
index 0000000..36f6258
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ContextPathTest.java
@@ -0,0 +1,293 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.servlet;
+
+import static org.easymock.EasyMock.createControl;
+import static org.easymock.EasyMock.expect;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Scopes;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import org.easymock.IMocksControl;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/** Tests to make sure that servlets with a context path are handled right. */
+public class ContextPathTest extends TestCase {
+
+  @Inject @Named("foo")
+  private TestServlet fooServlet;
+
+  @Inject @Named("bar") 
+  private TestServlet barServlet;
+
+  private IMocksControl globalControl;
+  private Injector injector;
+  private ServletContext servletContext;
+  private FilterConfig filterConfig;
+  private GuiceFilter guiceFilter;
+
+  @Override
+  public final void setUp() throws Exception {
+    injector = Guice.createInjector(new ServletModule() {
+      @Override
+      protected void configureServlets() {
+        bind(TestServlet.class).annotatedWith(Names.named("foo"))
+            .to(TestServlet.class).in(Scopes.SINGLETON);
+        bind(TestServlet.class).annotatedWith(Names.named("bar"))
+            .to(TestServlet.class).in(Scopes.SINGLETON);
+        serve("/foo/*").with(Key.get(TestServlet.class, Names.named("foo")));
+        serve("/bar/*").with(Key.get(TestServlet.class, Names.named("bar")));
+        // TODO: add a filter(..) call and validate it is correct
+      }
+    });
+    injector.injectMembers(this);
+
+    assertNotNull(fooServlet);
+    assertNotNull(barServlet);
+    assertNotSame(fooServlet, barServlet);
+
+    globalControl = createControl();
+    servletContext = globalControl.createMock(ServletContext.class);
+    filterConfig = globalControl.createMock(FilterConfig.class);
+
+    expect(servletContext.getAttribute(GuiceServletContextListener.INJECTOR_NAME))
+        .andReturn(injector).anyTimes();
+    expect(filterConfig.getServletContext()).andReturn(servletContext).anyTimes();
+
+    globalControl.replay();
+
+    guiceFilter = new GuiceFilter();
+    guiceFilter.init(filterConfig);
+  }
+
+  @Override
+  public final void tearDown() {
+    assertNotNull(fooServlet);
+    assertNotNull(barServlet);
+
+    fooServlet = null;
+    barServlet = null;
+
+    guiceFilter.destroy();
+    guiceFilter = null;
+
+    injector = null;
+
+    filterConfig = null;
+    servletContext = null;
+
+    globalControl.verify();
+  }
+
+  public void testSimple() throws Exception {
+    IMocksControl testControl = createControl();
+    TestFilterChain testFilterChain = new TestFilterChain();
+    HttpServletRequest req = testControl.createMock(HttpServletRequest.class);
+    HttpServletResponse res = testControl.createMock(HttpServletResponse.class);
+
+    expect(req.getMethod()).andReturn("GET").anyTimes();
+    expect(req.getRequestURI()).andReturn("/bar/foo").anyTimes();
+    expect(req.getServletPath()).andReturn("/bar/foo").anyTimes();
+    expect(req.getContextPath()).andReturn("").anyTimes();
+
+    testControl.replay();
+
+    guiceFilter.doFilter(req, res, testFilterChain);
+
+    assertFalse(testFilterChain.isTriggered());
+    assertFalse(fooServlet.isTriggered());
+    assertTrue(barServlet.isTriggered());
+
+    testControl.verify();
+  }
+
+  //
+  // each of the following "runTest" calls takes three path parameters:
+  //
+  // The value of "getRequestURI()"
+  // The value of "getServletPath()"
+  // The value of "getContextPath()"
+  //
+  // these values have been captured using a filter in Apache Tomcat 6.0.32
+  // and are used for real-world values that a servlet container would send into
+  // the GuiceFilter.
+  //
+  // the remaining three booleans are:
+  //
+  // True if the request gets passed down the filter chain
+  // True if the request hits the "foo" servlet
+  // True if the request hits the "bar" sevlet
+  //
+  // After adjusting the request URI for the web app deployment location, all
+  // calls
+  // should always produce the same result.
+  //
+
+  // ROOT Web app, using Tomcat default servlet
+  public void testRootDefault() throws Exception {
+    // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
+    runTest("/", "/", "", true, false, false);
+    // fetching /bar/. Should hit the bar servlet
+    runTest("/bar/", "/bar/", "", false, false, true);
+    // fetching /foo/xxx. Should hit the foo servlet
+    runTest("/foo/xxx", "/foo/xxx", "", false, true, false);
+    // fetching /xxx. Should go up the chain
+    runTest("/xxx", "/xxx", "", true, false, false);
+  }
+
+  // ROOT Web app, using explicit backing servlet mounted at /*
+  public void testRootExplicit() throws Exception {
+    // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
+    runTest("/", "", "", true, false, false);
+    // fetching /bar/. Should hit the bar servlet
+    runTest("/bar/", "", "", false, false, true);
+    // fetching /foo/xxx. Should hit the foo servlet
+    runTest("/foo/xxx", "", "", false, true, false);
+    // fetching /xxx. Should go up the chain
+    runTest("/xxx", "", "", true, false, false);
+  }
+
+  // ROOT Web app, using two backing servlets, mounted at /bar/* and /foo/*
+  public void testRootSpecific() throws Exception {
+    // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
+    runTest("/", "/", "", true, false, false);
+    // fetching /bar/. Should hit the bar servlet
+    runTest("/bar/", "/bar", "", false, false, true);
+    // fetching /foo/xxx. Should hit the foo servlet
+    runTest("/foo/xxx", "/foo", "", false, true, false);
+    // fetching /xxx. Should go up the chain
+    runTest("/xxx", "/xxx", "", true, false, false);
+  }
+
+  // Web app located at /webtest, using Tomcat default servlet
+  public void testWebtestDefault() throws Exception {
+    // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
+    runTest("/webtest/", "/", "/webtest", true, false, false);
+    // fetching /bar/. Should hit the bar servlet
+    runTest("/webtest/bar/", "/bar/", "/webtest", false, false, true);
+    // fetching /foo/xxx. Should hit the foo servlet
+    runTest("/webtest/foo/xxx", "/foo/xxx", "/webtest", false, true, false);
+    // fetching /xxx. Should go up the chain
+    runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false);
+  }
+
+  // Web app located at /webtest, using explicit backing servlet mounted at /*
+  public void testWebtestExplicit() throws Exception {
+    // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
+    runTest("/webtest/", "", "/webtest", true, false, false);
+    // fetching /bar/. Should hit the bar servlet
+    runTest("/webtest/bar/", "", "/webtest", false, false, true);
+    // fetching /foo/xxx. Should hit the foo servlet
+    runTest("/webtest/foo/xxx", "", "/webtest", false, true, false);
+    // fetching /xxx. Should go up the chain
+    runTest("/webtest/xxx", "", "/webtest", true, false, false);
+  }
+
+  // Web app located at /webtest, using two backing servlets, mounted at /bar/*
+  // and /foo/*
+  public void testWebtestSpecific() throws Exception {
+    // fetching /. Should go up the filter chain (only mappings on /foo/* and
+    // /bar/*).
+    runTest("/webtest/", "/", "/webtest", true, false, false);
+    // fetching /bar/. Should hit the bar servlet
+    runTest("/webtest/bar/", "/bar", "/webtest", false, false, true);
+    // fetching /foo/xxx. Should hit the foo servlet
+    runTest("/webtest/foo/xxx", "/foo", "/webtest", false, true, false);
+    // fetching /xxx. Should go up the chain
+    runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false);
+  }
+
+  private void runTest(final String requestURI, final String servletPath, final String contextPath,
+      final boolean filterResult, final boolean fooResult, final boolean barResult)
+      throws Exception {
+    IMocksControl testControl = createControl();
+
+    barServlet.clear();
+    fooServlet.clear();
+
+    TestFilterChain testFilterChain = new TestFilterChain();
+    HttpServletRequest req = testControl.createMock(HttpServletRequest.class);
+    HttpServletResponse res = testControl.createMock(HttpServletResponse.class);
+
+    expect(req.getMethod()).andReturn("GET").anyTimes();
+    expect(req.getRequestURI()).andReturn(requestURI).anyTimes();
+    expect(req.getServletPath()).andReturn(servletPath).anyTimes();
+    expect(req.getContextPath()).andReturn(contextPath).anyTimes();
+
+    testControl.replay();
+
+    guiceFilter.doFilter(req, res, testFilterChain);
+
+    assertEquals(filterResult, testFilterChain.isTriggered());
+    assertEquals(fooResult, fooServlet.isTriggered());
+    assertEquals(barResult, barServlet.isTriggered());
+
+    testControl.verify();
+  }
+
+  public static class TestServlet extends HttpServlet {
+    private boolean triggered = false;
+
+    @Override
+    public void doGet(HttpServletRequest req, HttpServletResponse resp) {
+      triggered = true;
+    }
+
+    public boolean isTriggered() {
+      return triggered;
+    }
+
+    public void clear() {
+      triggered = false;
+    }
+  }
+
+  public static class TestFilterChain implements FilterChain {
+    private boolean triggered = false;
+
+    public void doFilter(ServletRequest request, ServletResponse response) throws IOException,
+        ServletException {
+      triggered = true;
+    }
+
+    public boolean isTriggered() {
+      return triggered;
+    }
+
+    public void clear() {
+      triggered = false;
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ContinuingHttpServletRequestTest.java b/extensions/servlet/test/com/google/inject/servlet/ContinuingHttpServletRequestTest.java
new file mode 100644
index 0000000..778c9ad
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ContinuingHttpServletRequestTest.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright (C) 2013 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.inject.servlet;
+
+import junit.framework.AssertionFailedError;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import junit.framework.TestCase;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+
+public class ContinuingHttpServletRequestTest extends TestCase {
+
+  private static final String TEST_VALUE_1 = "testValue1";
+  private static final String TEST_VALUE_2 = "testValue2";
+  private static final int DEFAULT_MAX_AGE = new Cookie("", "").getMaxAge();
+
+  public void testReturnNullCookiesIfDelegateHasNoNull() {
+    HttpServletRequest delegate = createMock(HttpServletRequest.class);
+    expect(delegate.getCookies()).andStubReturn(null);
+
+    replay(delegate);
+
+    assertNull(new ContinuingHttpServletRequest(delegate).getCookies());
+
+    verify(delegate);
+  }
+  
+  public void testReturnDelegateCookies() {
+    Cookie[] cookies = new Cookie[]{
+        new Cookie("testName1", TEST_VALUE_1),
+        new Cookie("testName2", "testValue2")
+    };
+    HttpServletRequest delegate = createMock(HttpServletRequest.class);
+    expect(delegate.getCookies()).andStubReturn(cookies);
+
+    replay(delegate);
+
+    ContinuingHttpServletRequest continuingRequest = new ContinuingHttpServletRequest(
+        delegate);
+
+    assertCookieArraysEqual(cookies, continuingRequest.getCookies());
+
+    // Now mutate the original cookies, this shouldnt be reflected in the continued request.
+    cookies[0].setValue("INVALID");
+    cookies[1].setValue("INVALID");
+    cookies[1].setMaxAge(123);
+
+    try {
+      assertCookieArraysEqual(cookies, continuingRequest.getCookies());
+      fail();
+    } catch (AssertionFailedError e) {
+      // Expected.
+    }
+
+    // Verify that they remain equal to the original values.
+    assertEquals(TEST_VALUE_1, continuingRequest.getCookies()[0].getValue());
+    assertEquals(TEST_VALUE_2, continuingRequest.getCookies()[1].getValue());
+    assertEquals(DEFAULT_MAX_AGE, continuingRequest.getCookies()[1].getMaxAge());
+
+    // Perform a snapshot of the snapshot.
+    ContinuingHttpServletRequest furtherContinuingRequest = new ContinuingHttpServletRequest(
+        continuingRequest);
+
+    // The cookies should be fixed.
+    assertCookieArraysEqual(continuingRequest.getCookies(), furtherContinuingRequest.getCookies());
+
+    verify(delegate);
+  }
+
+  private static void assertCookieArraysEqual(Cookie[] one, Cookie[] two) {
+    assertEquals(one.length, two.length);
+    for (int i = 0; i < one.length; i++) {
+      Cookie cookie = one[i];
+      assertCookieEquality(cookie, two[i]);
+    }
+  }
+
+  private static void assertCookieEquality(Cookie one, Cookie two) {
+    assertEquals(one.getName(), two.getName());
+    assertEquals(one.getComment(), two.getComment());
+    assertEquals(one.getDomain(), two.getDomain());
+    assertEquals(one.getPath(), two.getPath());
+    assertEquals(one.getValue(), two.getValue());
+    assertEquals(one.getMaxAge(), two.getMaxAge());
+    assertEquals(one.getSecure(), two.getSecure());
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ContinuingRequestIntegrationTest.java b/extensions/servlet/test/com/google/inject/servlet/ContinuingRequestIntegrationTest.java
new file mode 100644
index 0000000..164369e
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ContinuingRequestIntegrationTest.java
@@ -0,0 +1,235 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import javax.servlet.http.Cookie;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Tests continuation of requests
+ */
+
+public class ContinuingRequestIntegrationTest extends TestCase {
+  private static final String PARAM_VALUE = "there";
+  private static final String PARAM_NAME = "hi";
+
+  private final AtomicBoolean failed = new AtomicBoolean(false);
+  private final AbstractExecutorService sameThreadExecutor = new AbstractExecutorService() {
+    public void shutdown() {
+    }
+
+    public List<Runnable> shutdownNow() {
+      return ImmutableList.of();
+    }
+
+    public boolean isShutdown() {
+      return true;
+    }
+
+    public boolean isTerminated() {
+      return true;
+    }
+
+    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+      return true;
+    }
+
+    public void execute(Runnable command) {
+      command.run();
+    }
+
+    @Override public <T> Future<T> submit(Callable<T> task) {
+      try {
+        task.call();
+        fail();
+      } catch (Exception e) {
+        // Expected.
+        assertTrue(e instanceof IllegalStateException);
+        failed.set(true);
+      }
+
+      return null;
+    }
+  };
+
+  private ExecutorService executor;
+  private Injector injector;
+
+  @Override protected void tearDown() throws Exception {
+    injector.getInstance(GuiceFilter.class).destroy();
+  }
+
+  public final void testRequestContinuesInOtherThread()
+      throws ServletException, IOException, InterruptedException {
+    executor = Executors.newSingleThreadExecutor();
+
+    injector = Guice.createInjector(new ServletModule() {
+      @Override protected void configureServlets() {
+        serve("/*").with(ContinuingServlet.class);
+
+        bind(ExecutorService.class).toInstance(executor);
+      }
+    });
+
+    FilterConfig filterConfig = createMock(FilterConfig.class);
+    expect(filterConfig.getServletContext()).andReturn(createMock(ServletContext.class));
+
+    GuiceFilter guiceFilter = injector.getInstance(GuiceFilter.class);
+
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+
+    expect(request.getRequestURI()).andReturn("/");
+    expect(request.getContextPath())
+        .andReturn("")
+        .anyTimes();
+    expect(request.getMethod()).andReturn("GET");
+    expect(request.getCookies()).andReturn(new Cookie[0]);
+
+    FilterChain filterChain = createMock(FilterChain.class);
+    expect(request.getParameter(PARAM_NAME)).andReturn(PARAM_VALUE);
+
+    replay(request, filterConfig, filterChain);
+
+    guiceFilter.init(filterConfig);
+    guiceFilter.doFilter(request, null, filterChain);
+
+    // join.
+    executor.shutdown();
+    executor.awaitTermination(10, TimeUnit.SECONDS);
+
+    assertEquals(PARAM_VALUE, injector.getInstance(OffRequestCallable.class).value);
+    verify(request, filterConfig, filterChain);
+  }
+
+  public final void testRequestContinuationDiesInHttpRequestThread()
+      throws ServletException, IOException, InterruptedException {
+    executor = sameThreadExecutor;
+    injector = Guice.createInjector(new ServletModule() {
+      @Override protected void configureServlets() {
+        serve("/*").with(ContinuingServlet.class);
+
+        bind(ExecutorService.class).toInstance(executor);
+
+        bind(SomeObject.class);
+      }
+    });
+
+    FilterConfig filterConfig = createMock(FilterConfig.class);
+    expect(filterConfig.getServletContext()).andReturn(createMock(ServletContext.class));
+
+    GuiceFilter guiceFilter = injector.getInstance(GuiceFilter.class);
+
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+
+    expect(request.getRequestURI()).andReturn("/");
+    expect(request.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    expect(request.getMethod()).andReturn("GET");
+    expect(request.getCookies()).andReturn(new Cookie[0]);
+    FilterChain filterChain = createMock(FilterChain.class);
+
+    replay(request, filterConfig, filterChain);
+
+    guiceFilter.init(filterConfig);
+    guiceFilter.doFilter(request, null, filterChain);
+
+    // join.
+    executor.shutdown();
+    executor.awaitTermination(10, TimeUnit.SECONDS);
+
+    assertTrue(failed.get());
+    assertFalse(PARAM_VALUE.equals(injector.getInstance(OffRequestCallable.class).value));
+
+    verify(request, filterConfig, filterChain);
+  }
+
+  @RequestScoped
+  public static class SomeObject {
+  }
+
+  @Singleton
+  public static class ContinuingServlet extends HttpServlet {
+    @Inject OffRequestCallable callable;
+    @Inject ExecutorService executorService;
+
+    private SomeObject someObject;
+
+    @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+      assertNull(someObject);
+
+      // Seed with someobject.
+      someObject = new SomeObject();
+      Callable<String> task = ServletScopes.continueRequest(callable,
+          ImmutableMap.<Key<?>, Object>of(Key.get(SomeObject.class), someObject));
+
+      executorService.submit(task);
+    }
+  }
+
+  @Singleton
+  public static class OffRequestCallable implements Callable<String> {
+    @Inject Provider<HttpServletRequest> request;
+    @Inject Provider<HttpServletResponse> response;
+    @Inject Provider<SomeObject> someObject;
+
+    public String value;
+
+    public String call() throws Exception {
+      assertNull(response.get());
+
+      // Inside this request, we should always get the same instance.
+      assertSame(someObject.get(), someObject.get());
+
+      return value = request.get().getParameter(PARAM_NAME);
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/DummyFilterImpl.java b/extensions/servlet/test/com/google/inject/servlet/DummyFilterImpl.java
new file mode 100644
index 0000000..c931801
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/DummyFilterImpl.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * Used in unit tests to verify the EDSL.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail com)
+ */
+public class DummyFilterImpl implements Filter {
+  int num;
+
+  public DummyFilterImpl() {
+  }
+
+  public DummyFilterImpl(int num) {
+    this.num = num;
+  }
+
+  public void init(FilterConfig filterConfig) throws ServletException {
+  }
+
+  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+      FilterChain filterChain) throws IOException, ServletException {
+  }
+
+  public void destroy() {
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/DummyServlet.java b/extensions/servlet/test/com/google/inject/servlet/DummyServlet.java
new file mode 100644
index 0000000..861f8e0
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/DummyServlet.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.inject.Singleton;
+
+import javax.servlet.http.HttpServlet;
+
+/**
+ * Used in unit tests to verify the EDSL.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail com)
+ */
+@Singleton
+public class DummyServlet extends HttpServlet {
+
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/EdslTest.java b/extensions/servlet/test/com/google/inject/servlet/EdslTest.java
new file mode 100644
index 0000000..5c62116
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/EdslTest.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Singleton;
+import com.google.inject.Stage;
+
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+
+/**
+ * Sanity checks the EDSL and resultant bound module(s).
+ *
+ * @author Dhanji R. Prasanna (dhanji gmail com)
+ */
+public class EdslTest extends TestCase {
+
+  public final void testExplicitBindingsWorksWithGuiceServlet() {
+    Injector injector = Guice.createInjector(
+        new AbstractModule() {
+          @Override
+          protected void configure() {
+            binder().requireExplicitBindings();
+          }
+        }, new ServletModule() {
+          @Override protected void configureServlets() {
+            bind(DummyServlet.class).in(Singleton.class);
+            serve("/*").with(DummyServlet.class);
+          }
+        });
+
+    assertNotNull(injector.getInstance(DummyServlet.class));
+  }
+
+  public final void testConfigureServlets() {
+
+    //the various possible config calls--
+    Module webModule = new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("/*").through(DummyFilterImpl.class);
+        filter("*.html").through(DummyFilterImpl.class);
+        filter("/*").through(Key.get(DummyFilterImpl.class));
+        filter("/*").through(new DummyFilterImpl());
+
+        filter("*.html").through(DummyFilterImpl.class,
+            new HashMap<String, String>());
+
+        filterRegex("/person/[0-9]*").through(DummyFilterImpl.class);
+        filterRegex("/person/[0-9]*").through(DummyFilterImpl.class,
+            new HashMap<String, String>());
+
+        filterRegex("/person/[0-9]*").through(Key.get(DummyFilterImpl.class));
+        filterRegex("/person/[0-9]*").through(Key.get(DummyFilterImpl.class),
+            new HashMap<String, String>());
+
+        filterRegex("/person/[0-9]*").through(new DummyFilterImpl());
+        filterRegex("/person/[0-9]*").through(new DummyFilterImpl(),
+            new HashMap<String, String>());
+
+
+        serve("/1/*").with(DummyServlet.class);
+        serve("/2/*").with(Key.get(DummyServlet.class));
+        serve("/3/*").with(new DummyServlet());
+        serve("/4/*").with(DummyServlet.class, new HashMap<String, String>());
+
+        serve("*.htm").with(Key.get(DummyServlet.class));
+        serve("*.html").with(Key.get(DummyServlet.class),
+            new HashMap<String, String>());
+
+        serveRegex("/person/[0-8]*").with(DummyServlet.class);
+        serveRegex("/person/[0-9]*").with(DummyServlet.class,
+            new HashMap<String, String>());
+
+        serveRegex("/person/[0-6]*").with(Key.get(DummyServlet.class));
+        serveRegex("/person/[0-9]/2/*").with(Key.get(DummyServlet.class),
+            new HashMap<String, String>());
+
+        serveRegex("/person/[0-5]*").with(new DummyServlet());
+        serveRegex("/person/[0-9]/3/*").with(new DummyServlet(),
+            new HashMap<String, String>());
+      }
+    };
+
+    //verify that it doesn't blow up!
+    Guice.createInjector(Stage.TOOL, webModule);
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ExtensionSpiTest.java b/extensions/servlet/test/com/google/inject/servlet/ExtensionSpiTest.java
new file mode 100644
index 0000000..e6ca1cf
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ExtensionSpiTest.java
@@ -0,0 +1,192 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import static com.google.inject.servlet.UriPatternType.REGEX;
+import static com.google.inject.servlet.UriPatternType.SERVLET;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.name.Names;
+import com.google.inject.servlet.ServletSpiVisitor.Params;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+
+import junit.framework.TestCase;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A very basic test that servletmodule works with bindings.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class ExtensionSpiTest extends TestCase {
+
+  private DummyFilterImpl dummyFilter1 = new DummyFilterImpl();
+  private DummyFilterImpl dummyFilter2 = new DummyFilterImpl();
+  private DummyFilterImpl dummyFilter3 = new DummyFilterImpl();
+  private DummyFilterImpl dummyFilter4 = new DummyFilterImpl();
+
+  private DummyServlet dummyServlet1 = new DummyServlet();
+  private DummyServlet dummyServlet2 = new DummyServlet();
+  private DummyServlet dummyServlet3 = new DummyServlet();
+  private DummyServlet dummyServlet4 = new DummyServlet();
+
+  public final void testSpiOnElements() {
+    ServletSpiVisitor visitor = new ServletSpiVisitor(false);
+    int count = 0;
+    for(Element element : Elements.getElements(new Module())) {
+      if(element instanceof Binding) {
+        assertEquals(count++, ((Binding)element).acceptTargetVisitor(visitor));
+      }
+    }
+    validateVisitor(visitor);
+  }
+
+  public final void testSpiOnInjector() {
+    ServletSpiVisitor visitor = new ServletSpiVisitor(true);
+    int count = 0;
+    Injector injector = Guice.createInjector(new Module());
+    for(Binding binding : injector.getBindings().values()) {
+      assertEquals(count++, binding.acceptTargetVisitor(visitor));
+    }
+    validateVisitor(visitor);
+  }
+
+  private void validateVisitor(ServletSpiVisitor visitor) {
+    assertEquals(48, visitor.currentCount - visitor.otherCount);
+
+    // This is the expected param list, in order..
+    List<Params> expected = ImmutableList.of(
+        new Params("/class", Key.get(DummyFilterImpl.class), ImmutableMap.of(), SERVLET),
+        new Params("/class/2", Key.get(DummyFilterImpl.class), ImmutableMap.of(), SERVLET),
+        new Params("/key", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), SERVLET),
+        new Params("/key/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), SERVLET),
+        new Params("/instance", dummyFilter1, ImmutableMap.of(), SERVLET),
+        new Params("/instance/2", dummyFilter1, ImmutableMap.of(), SERVLET),
+        new Params("/class/keyvalues", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/class/keyvalues/2", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/key/keyvalues", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/key/keyvalues/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/instance/keyvalues", dummyFilter2, ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/instance/keyvalues/2", dummyFilter2, ImmutableMap.of("key", "value"), SERVLET),
+
+        new Params("/class[0-9]", Key.get(DummyFilterImpl.class), ImmutableMap.of(), REGEX),
+        new Params("/class[0-9]/2", Key.get(DummyFilterImpl.class), ImmutableMap.of(), REGEX),
+        new Params("/key[0-9]", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), REGEX),
+        new Params("/key[0-9]/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), REGEX),
+        new Params("/instance[0-9]", dummyFilter3, ImmutableMap.of(), REGEX),
+        new Params("/instance[0-9]/2", dummyFilter3, ImmutableMap.of(), REGEX),
+        new Params("/class[0-9]/keyvalues", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), REGEX),
+        new Params("/class[0-9]/keyvalues/2", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), REGEX),
+        new Params("/key[0-9]/keyvalues", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX),
+        new Params("/key[0-9]/keyvalues/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX),
+        new Params("/instance[0-9]/keyvalues", dummyFilter4, ImmutableMap.of("key", "value"), REGEX),
+        new Params("/instance[0-9]/keyvalues/2", dummyFilter4, ImmutableMap.of("key", "value"), REGEX),
+
+        new Params("/class", Key.get(DummyServlet.class), ImmutableMap.of(), SERVLET),
+        new Params("/class/2", Key.get(DummyServlet.class), ImmutableMap.of(), SERVLET),
+        new Params("/key", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), SERVLET),
+        new Params("/key/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), SERVLET),
+        new Params("/instance", dummyServlet1, ImmutableMap.of(), SERVLET),
+        new Params("/instance/2", dummyServlet1, ImmutableMap.of(), SERVLET),
+        new Params("/class/keyvalues", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/class/keyvalues/2", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/key/keyvalues", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/key/keyvalues/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/instance/keyvalues", dummyServlet2, ImmutableMap.of("key", "value"), SERVLET),
+        new Params("/instance/keyvalues/2", dummyServlet2, ImmutableMap.of("key", "value"), SERVLET),
+
+        new Params("/class[0-9]", Key.get(DummyServlet.class), ImmutableMap.of(), REGEX),
+        new Params("/class[0-9]/2", Key.get(DummyServlet.class), ImmutableMap.of(), REGEX),
+        new Params("/key[0-9]", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), REGEX),
+        new Params("/key[0-9]/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), REGEX),
+        new Params("/instance[0-9]", dummyServlet3, ImmutableMap.of(), REGEX),
+        new Params("/instance[0-9]/2", dummyServlet3, ImmutableMap.of(), REGEX),
+        new Params("/class[0-9]/keyvalues", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), REGEX),
+        new Params("/class[0-9]/keyvalues/2", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), REGEX),
+        new Params("/key[0-9]/keyvalues", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX),
+        new Params("/key[0-9]/keyvalues/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX),
+        new Params("/instance[0-9]/keyvalues", dummyServlet4, ImmutableMap.of("key", "value"), REGEX),
+        new Params("/instance[0-9]/keyvalues/2", dummyServlet4, ImmutableMap.of("key", "value"), REGEX)
+    );
+
+    assertEquals(expected.size(), visitor.actual.size());
+    Iterator<Params> actualIterator = visitor.actual.iterator();
+    int i = 0;
+    for(Params param : expected) {
+      assertEquals("wrong " + i++ + "th param", param, actualIterator.next());
+    }
+  }
+
+  private class Module extends ServletModule {
+    @Override
+    protected void configureServlets() {
+      binder().requireExplicitBindings();
+
+      filter("/class", "/class/2").through(DummyFilterImpl.class);
+      filter("/key", "/key/2").through(
+          Key.get(DummyFilterImpl.class, Names.named("foo")));
+      filter("/instance", "/instance/2").through(dummyFilter1);
+      filter("/class/keyvalues", "/class/keyvalues/2").through(
+          DummyFilterImpl.class, ImmutableMap.of("key", "value"));
+      filter("/key/keyvalues", "/key/keyvalues/2").through(
+          Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"));
+      filter("/instance/keyvalues", "/instance/keyvalues/2").through(
+          dummyFilter2, ImmutableMap.of("key", "value"));
+
+      filterRegex("/class[0-9]", "/class[0-9]/2").through(DummyFilterImpl.class);
+      filterRegex("/key[0-9]", "/key[0-9]/2").through(
+          Key.get(DummyFilterImpl.class, Names.named("foo")));
+      filterRegex("/instance[0-9]", "/instance[0-9]/2").through(dummyFilter3);
+      filterRegex("/class[0-9]/keyvalues", "/class[0-9]/keyvalues/2").through(
+          DummyFilterImpl.class, ImmutableMap.of("key", "value"));
+      filterRegex("/key[0-9]/keyvalues", "/key[0-9]/keyvalues/2").through(
+          Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"));
+      filterRegex("/instance[0-9]/keyvalues", "/instance[0-9]/keyvalues/2").through(
+          dummyFilter4, ImmutableMap.of("key", "value"));
+
+      serve("/class", "/class/2").with(DummyServlet.class);
+      serve("/key", "/key/2").with(
+          Key.get(DummyServlet.class, Names.named("foo")));
+      serve("/instance", "/instance/2").with(dummyServlet1);
+      serve("/class/keyvalues", "/class/keyvalues/2").with(
+          DummyServlet.class, ImmutableMap.of("key", "value"));
+      serve("/key/keyvalues", "/key/keyvalues/2").with(
+          Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"));
+      serve("/instance/keyvalues", "/instance/keyvalues/2").with(
+          dummyServlet2, ImmutableMap.of("key", "value"));
+
+      serveRegex("/class[0-9]", "/class[0-9]/2").with(DummyServlet.class);
+      serveRegex("/key[0-9]", "/key[0-9]/2").with(
+          Key.get(DummyServlet.class, Names.named("foo")));
+      serveRegex("/instance[0-9]", "/instance[0-9]/2").with(dummyServlet3);
+      serveRegex("/class[0-9]/keyvalues", "/class[0-9]/keyvalues/2").with(
+          DummyServlet.class, ImmutableMap.of("key", "value"));
+      serveRegex("/key[0-9]/keyvalues", "/key[0-9]/keyvalues/2").with(
+          Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"));
+      serveRegex("/instance[0-9]/keyvalues", "/instance[0-9]/keyvalues/2").with(
+          dummyServlet4, ImmutableMap.of("key", "value"));
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java b/extensions/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java
new file mode 100644
index 0000000..136a3cd
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java
@@ -0,0 +1,309 @@
+package com.google.inject.servlet;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.spi.BindingScopingVisitor;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Tests the lifecycle of the encapsulated {@link FilterDefinition} class.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail com)
+ */
+public class FilterDefinitionTest extends TestCase {
+
+  public final void testFilterInitAndConfig() throws ServletException {
+
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+
+    final MockFilter mockFilter = new MockFilter();
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(Filter.class)))
+        .andReturn(binding);
+
+    expect(injector.getInstance(Key.get(Filter.class)))
+        .andReturn(mockFilter)
+        .anyTimes();
+
+    replay(binding, injector);
+
+    //some init params
+    //noinspection SSBasedInspection
+    final Map<String, String> initParams = new ImmutableMap.Builder<String, String>()
+      .put("ahsd", "asdas24dok")
+      .put("ahssd", "asdasd124ok").build();
+
+    ServletContext servletContext = createMock(ServletContext.class);
+    final String contextName = "thing__!@@44";
+    expect(servletContext.getServletContextName()).andReturn(contextName);
+
+    replay(servletContext);
+
+    String pattern = "/*";
+    final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class),
+        UriPatternType.get(UriPatternType.SERVLET, pattern), initParams, null);
+    filterDef.init(servletContext, injector, Sets.<Filter>newIdentityHashSet());
+
+    assertTrue(filterDef.getFilter() instanceof MockFilter);
+    final FilterConfig filterConfig = mockFilter.getConfig();
+    assertTrue(null != filterConfig);
+    assertEquals(filterConfig.getServletContext().getServletContextName(), contextName);
+    assertEquals(filterConfig.getFilterName(), Key.get(Filter.class).toString());
+
+    final Enumeration names = filterConfig.getInitParameterNames();
+    while (names.hasMoreElements()) {
+      String name = (String) names.nextElement();
+
+      assertTrue(initParams.containsKey(name));
+      assertEquals(filterConfig.getInitParameter(name), initParams.get(name));
+    }
+
+    verify(binding, injector, servletContext);
+  }
+
+  public final void testFilterCreateDispatchDestroy() throws ServletException, IOException {
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+
+    final MockFilter mockFilter = new MockFilter();
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(Filter.class)))
+        .andReturn(binding);
+
+    expect(injector.getInstance(Key.get(Filter.class)))
+        .andReturn(mockFilter)
+        .anyTimes();
+
+    expect(request.getRequestURI()).andReturn("/index.html");
+    expect(request.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    replay(injector, binding, request);
+
+    String pattern = "/*";
+    final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class),
+        UriPatternType.get(UriPatternType.SERVLET, pattern),
+        new HashMap<String, String>(), null);
+    //should fire on mockfilter now
+    filterDef.init(createMock(ServletContext.class), injector, Sets.<Filter>newIdentityHashSet());
+    assertTrue(filterDef.getFilter() instanceof MockFilter);
+
+    assertTrue("Init did not fire", mockFilter.isInit());
+
+    Filter matchingFilter = filterDef.getFilterIfMatching(request);
+    assertSame(mockFilter, matchingFilter);
+
+    final boolean proceed[] = new boolean[1];
+    matchingFilter.doFilter(request, null, new FilterChainInvocation(null, null, null) {
+      @Override
+      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+        proceed[0] = true;
+      }
+    });
+
+    assertTrue("Filter did not proceed down chain", proceed[0]);
+
+    filterDef.destroy(Sets.<Filter>newIdentityHashSet());
+    assertTrue("Destroy did not fire", mockFilter.isDestroy());
+
+    verify(injector, request);
+
+  }
+
+  public final void testFilterCreateDispatchDestroySupressChain()
+      throws ServletException, IOException {
+
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+
+    final MockFilter mockFilter = new MockFilter() {
+      @Override
+      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+          FilterChain filterChain) {
+        //suppress rest of chain...
+      }
+    };
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(Filter.class)))
+        .andReturn(binding);
+
+    expect(injector.getInstance(Key.get(Filter.class)))
+        .andReturn(mockFilter)
+        .anyTimes();
+
+    expect(request.getRequestURI()).andReturn("/index.html");
+    expect(request.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    replay(injector, binding, request);
+
+    String pattern = "/*";
+    final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class),
+        UriPatternType.get(UriPatternType.SERVLET, pattern),
+        new HashMap<String, String>(), null);
+    //should fire on mockfilter now
+    filterDef.init(createMock(ServletContext.class), injector, Sets.<Filter>newIdentityHashSet());
+    assertTrue(filterDef.getFilter() instanceof MockFilter);
+
+
+    assertTrue("init did not fire", mockFilter.isInit());
+
+    Filter matchingFilter = filterDef.getFilterIfMatching(request);
+    assertSame(mockFilter, matchingFilter);
+
+    final boolean proceed[] = new boolean[1];
+    matchingFilter.doFilter(request, null, new FilterChainInvocation(null, null, null) {
+      @Override
+      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+        proceed[0] = true;
+      }
+    });
+
+    assertFalse("filter did not suppress chain", proceed[0]);
+
+    filterDef.destroy(Sets.<Filter>newIdentityHashSet());
+    assertTrue("destroy did not fire", mockFilter.isDestroy());
+
+    verify(injector, request);
+
+  }
+
+  public void testGetFilterIfMatching() throws ServletException {
+    String pattern = "/*";
+    final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class),
+        UriPatternType.get(UriPatternType.SERVLET, pattern),
+        new HashMap<String, String>(), null);
+    HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+    ServletContext servletContext = createMock(ServletContext.class);
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+
+    final MockFilter mockFilter = new MockFilter() {
+      @Override
+      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+          FilterChain filterChain) {
+        //suppress rest of chain...
+      }
+    };
+    expect(injector.getBinding(Key.get(Filter.class)))
+        .andReturn(binding);
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getInstance(Key.get(Filter.class)))
+        .andReturn(mockFilter)
+        .anyTimes();
+
+    expect(servletRequest.getContextPath()).andReturn("/a_context_path");
+    expect(servletRequest.getRequestURI()).andReturn("/a_context_path/test.html");
+
+    replay(servletRequest, binding, injector);
+    filterDef.init(servletContext, injector, Sets.<Filter>newIdentityHashSet());
+    Filter filter = filterDef.getFilterIfMatching(servletRequest);
+    assertSame(filter, mockFilter);
+    verify(servletRequest, binding, injector);
+  }
+
+  public void testGetFilterIfMatchingNotMatching() throws ServletException {
+    String pattern = "/*";
+    final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class),
+        UriPatternType.get(UriPatternType.SERVLET, pattern),
+        new HashMap<String, String>(), null);
+    HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+    ServletContext servletContext = createMock(ServletContext.class);
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+
+    final MockFilter mockFilter = new MockFilter() {
+      @Override
+      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+          FilterChain filterChain) {
+        //suppress rest of chain...
+      }
+    };
+    expect(injector.getBinding(Key.get(Filter.class)))
+        .andReturn(binding);
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getInstance(Key.get(Filter.class)))
+        .andReturn(mockFilter)
+        .anyTimes();
+
+    expect(servletRequest.getContextPath()).andReturn("/a_context_path");
+    expect(servletRequest.getRequestURI()).andReturn("/test.html");
+
+    replay(servletRequest, binding, injector);
+    filterDef.init(servletContext, injector, Sets.<Filter>newIdentityHashSet());
+    Filter filter = filterDef.getFilterIfMatching(servletRequest);
+    assertNull(filter);
+    verify(servletRequest, binding, injector);
+  }
+
+  private static class MockFilter implements Filter {
+    private boolean init;
+    private boolean destroy;
+    private FilterConfig config;
+
+    public void init(FilterConfig filterConfig) {
+      init = true;
+
+      this.config = filterConfig;
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      //proceed
+      filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    public void destroy() {
+      destroy = true;
+    }
+
+    public boolean isInit() {
+      return init;
+    }
+
+    public boolean isDestroy() {
+      return destroy;
+    }
+
+    public FilterConfig getConfig() {
+      return config;
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java b/extensions/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java
new file mode 100644
index 0000000..1d55ec1
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java
@@ -0,0 +1,391 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.servlet;
+
+import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
+import static com.google.inject.servlet.ServletTestUtils.newFakeHttpServletRequest;
+import static com.google.inject.servlet.ServletTestUtils.newNoOpFilterChain;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * This tests that filter stage of the pipeline dispatches
+ * correctly to guice-managed filters.
+ *
+ * WARNING(dhanji): Non-parallelizable test =(
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class FilterDispatchIntegrationTest extends TestCase {
+    private static int inits, doFilters, destroys;
+
+  private IMocksControl control;
+
+  @Override
+  public final void setUp() {
+    inits = 0;
+    doFilters = 0;
+    destroys = 0;
+    control = EasyMock.createControl();
+    GuiceFilter.reset();
+  }
+
+
+  public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("/*").through(TestFilter.class);
+        filter("*.html").through(TestFilter.class);
+        filter("/*").through(Key.get(TestFilter.class));
+
+        // These filters should never fire
+        filter("/index/*").through(Key.get(TestFilter.class));
+        filter("*.jsp").through(Key.get(TestFilter.class));
+
+        // Bind a servlet
+        serve("*.html").with(TestServlet.class);
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);
+
+    // create ourselves a mock request with test URI
+    HttpServletRequest requestMock = control.createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+            .andReturn("/index.html")
+            .anyTimes();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true);
+    requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST);
+
+    HttpServletResponse responseMock = control.createMock(HttpServletResponse.class);
+    expect(responseMock.isCommitted())
+        .andReturn(false)
+        .anyTimes();
+    responseMock.resetBuffer();
+    expectLastCall().anyTimes();
+
+    FilterChain filterChain = control.createMock(FilterChain.class);
+
+    //dispatch request
+    control.replay();
+    pipeline.dispatch(requestMock, responseMock, filterChain);
+    pipeline.destroyPipeline();
+    control.verify();
+
+    TestServlet servlet = injector.getInstance(TestServlet.class);
+    assertEquals(2, servlet.processedUris.size());
+    assertTrue(servlet.processedUris.contains("/index.html"));
+    assertTrue(servlet.processedUris.contains(TestServlet.FORWARD_TO));
+
+    assertTrue("lifecycle states did not"
+        + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters
+        + "; destroys: " + destroys, inits == 1 && doFilters == 3 && destroys == 1);
+  }
+
+  public final void testDispatchThatNoFiltersFire() throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("/public/*").through(TestFilter.class);
+        filter("*.html").through(TestFilter.class);
+        filter("*.xml").through(Key.get(TestFilter.class));
+
+        // These filters should never fire
+        filter("/index/*").through(Key.get(TestFilter.class));
+        filter("*.jsp").through(Key.get(TestFilter.class));
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = control.createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+            .andReturn("/index.xhtml")
+            .anyTimes();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    FilterChain filterChain = control.createMock(FilterChain.class);
+    filterChain.doFilter(requestMock, null);
+    control.replay();
+    pipeline.dispatch(requestMock, null, filterChain);
+    pipeline.destroyPipeline();
+    control.verify();
+
+    assertTrue("lifecycle states did not "
+        + "fire correct number of times-- inits: " + inits + "; dos: " + doFilters
+        + "; destroys: " + destroys,
+        inits == 1 && doFilters == 0 && destroys == 1);
+  }
+
+  public final void testDispatchFilterPipelineWithRegexMatching() throws ServletException,
+      IOException {
+
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filterRegex("/[A-Za-z]*").through(TestFilter.class);
+        filterRegex("/index").through(TestFilter.class);
+        //these filters should never fire
+        filterRegex("\\w").through(Key.get(TestFilter.class));
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = control.createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+            .andReturn("/index")
+            .anyTimes();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    // dispatch request
+    FilterChain filterChain = control.createMock(FilterChain.class);
+    filterChain.doFilter(requestMock, null);
+    control.replay();
+    pipeline.dispatch(requestMock, null, filterChain);
+    pipeline.destroyPipeline();
+    control.verify();
+
+    assertTrue("lifecycle states did not fire "
+        + "correct number of times-- inits: " + inits + "; dos: " + doFilters
+        + "; destroys: " + destroys,
+        inits == 1 && doFilters == 2 && destroys == 1);
+  }
+
+  @Singleton
+  public static class TestFilter implements Filter {
+    public void init(FilterConfig filterConfig) {
+      inits++;
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      doFilters++;
+      filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+
+  @Singleton
+  public static class TestServlet extends HttpServlet {
+    public static final String FORWARD_FROM = "/index.html";
+    public static final String FORWARD_TO = "/forwarded.html";
+    public List<String> processedUris = new ArrayList<String>();
+
+    @Override
+    protected void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
+        throws ServletException, IOException {
+      String requestUri = httpServletRequest.getRequestURI();
+      processedUris.add(requestUri);
+
+      // If the client is requesting /index.html then we forward to /forwarded.html
+      if (FORWARD_FROM.equals(requestUri)) {
+        httpServletRequest.getRequestDispatcher(FORWARD_TO)
+            .forward(httpServletRequest, httpServletResponse);
+      }
+    }
+
+    @Override
+    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
+        throws ServletException, IOException {
+      service((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
+    }
+  }
+  
+  public void testFilterOrder() throws Exception {
+    AtomicInteger counter = new AtomicInteger();
+    final CountFilter f1 = new CountFilter(counter);
+    final CountFilter f2 = new CountFilter(counter);
+    
+    Injector injector = Guice.createInjector(new ServletModule() {
+      @Override
+      protected void configureServlets() {
+        filter("/").through(f1);
+        install(new ServletModule() {
+          @Override
+          protected void configureServlets() {
+            filter("/").through(f2);
+          }
+        });
+      }
+    });
+    
+    HttpServletRequest request = newFakeHttpServletRequest();    
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);    
+    pipeline.dispatch(request, null, newNoOpFilterChain());
+    assertEquals(0, f1.calledAt);
+    assertEquals(1, f2.calledAt);
+  }
+  
+  /** A filter that keeps count of when it was called by increment a counter. */
+  private static class CountFilter implements Filter {
+    private final AtomicInteger counter;
+    private int calledAt = -1;
+
+    public CountFilter(AtomicInteger counter) {
+      this.counter = counter;
+    }
+    
+    public void destroy() {
+    }
+    
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws ServletException, IOException {
+      if (calledAt != -1) {
+        fail("not expecting to be called twice");
+      }
+      calledAt = counter.getAndIncrement();
+      chain.doFilter(request, response);
+    }
+    
+    public void init(FilterConfig filterConfig) {}
+  }
+  
+  public final void testFilterExceptionPrunesStack() throws Exception {
+    Injector injector = Guice.createInjector(new ServletModule() {
+      @Override
+      protected void configureServlets() {
+        filter("/").through(TestFilter.class);
+        filter("/nothing").through(TestFilter.class);
+        filter("/").through(ThrowingFilter.class);
+      }
+    });
+
+    HttpServletRequest request = newFakeHttpServletRequest();    
+    FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);    
+    try {
+      pipeline.dispatch(request, null, null);
+      fail("expected exception");
+    } catch(ServletException ex) {
+      for (StackTraceElement element : ex.getStackTrace()) {
+        String className = element.getClassName();
+        assertTrue("was: " + element,
+            !className.equals(FilterChainInvocation.class.getName())
+            && !className.equals(FilterDefinition.class.getName()));
+      }
+    }
+  }
+  
+  public final void testServletExceptionPrunesStack() throws Exception {
+    Injector injector = Guice.createInjector(new ServletModule() {
+      @Override
+      protected void configureServlets() {
+        filter("/").through(TestFilter.class);
+        filter("/nothing").through(TestFilter.class);
+        serve("/").with(ThrowingServlet.class);
+      }
+    });
+
+    HttpServletRequest request = newFakeHttpServletRequest();    
+    FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);    
+    try {
+      pipeline.dispatch(request, null, null);
+      fail("expected exception");
+    } catch(ServletException ex) {
+      for (StackTraceElement element : ex.getStackTrace()) {
+        String className = element.getClassName();
+        assertTrue("was: " + element,
+            !className.equals(FilterChainInvocation.class.getName())
+            && !className.equals(FilterDefinition.class.getName()));
+      }
+    }
+  }
+  
+  @Singleton
+  private static class ThrowingServlet extends HttpServlet {
+
+    @Override
+    protected void service(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException {
+      throw new ServletException("failure!");
+    }
+    
+  }
+
+
+  @Singleton
+  private static class ThrowingFilter implements Filter {
+    @Override
+    public void destroy() {
+    }
+    
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws ServletException {
+      throw new ServletException("we failed!");
+    }
+    
+    @Override
+    public void init(FilterConfig filterConfig) {
+
+    }
+    
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/FilterPipelineTest.java b/extensions/servlet/test/com/google/inject/servlet/FilterPipelineTest.java
new file mode 100644
index 0000000..06e3990
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/FilterPipelineTest.java
@@ -0,0 +1,126 @@
+package com.google.inject.servlet;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.isNull;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.inject.Guice;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This is a basic whitebox test that verifies the glue between
+ * GuiceFilter and ManagedFilterPipeline is working.
+ * 
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class FilterPipelineTest extends TestCase {
+
+  @Override
+  public final void setUp() {
+    GuiceFilter.reset();
+    
+    Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+          filter("/*").through(TestFilter.class);
+          filter("*.html").through(TestFilter.class);
+          filter("/*").through(Key.get(TestFilter.class));
+          filter("*.jsp").through(Key.get(TestFilter.class));
+
+          // These filters should never fire
+          filter("/index/*").through(Key.get(NeverFilter.class));
+          filter("/public/login/*").through(Key.get(NeverFilter.class));
+      }
+    });
+  }
+
+  @Override
+  public final void tearDown() {
+    GuiceFilter.reset();
+  }
+
+  public final void testDispatchThruGuiceFilter() throws ServletException, IOException {
+
+    //create mocks
+    FilterConfig filterConfig = createMock(FilterConfig.class);
+    ServletContext servletContext = createMock(ServletContext.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    FilterChain proceedingFilterChain = createMock(FilterChain.class);
+
+    //begin mock script ***
+
+    expect(filterConfig.getServletContext())
+        .andReturn(servletContext)
+        .once();
+
+    expect(request.getRequestURI())
+        .andReturn("/public/login.jsp")
+        .anyTimes();
+    expect(request.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //at the end, proceed down webapp's normal filter chain
+    proceedingFilterChain.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull());
+    expectLastCall().once();
+
+    //run mock script ***
+    replay(filterConfig, servletContext, request, proceedingFilterChain);
+
+    final GuiceFilter webFilter = new GuiceFilter();
+
+    webFilter.init(filterConfig);
+    webFilter.doFilter(request, null, proceedingFilterChain);
+    webFilter.destroy();
+
+    //assert expectations
+    verify(filterConfig, servletContext, request, proceedingFilterChain);
+  }
+
+  @Singleton
+  public static class TestFilter implements Filter {
+    public void init(FilterConfig filterConfig) {
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    public void destroy() {
+    }
+  }
+
+  @Singleton
+  public static class NeverFilter implements Filter {
+    public void init(FilterConfig filterConfig) {
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) {
+      fail("This filter should never have fired");
+    }
+
+    public void destroy() {
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/InjectedFilterPipelineTest.java b/extensions/servlet/test/com/google/inject/servlet/InjectedFilterPipelineTest.java
new file mode 100644
index 0000000..020f277
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/InjectedFilterPipelineTest.java
@@ -0,0 +1,181 @@
+package com.google.inject.servlet;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.isNull;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Exactly the same as {@linkplain com.google.inject.servlet.FilterPipelineTest} except
+ * that we test that the static pipeline is not used.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class InjectedFilterPipelineTest extends TestCase {
+  private Injector injector1;
+  private Injector injector2;
+
+  @Override
+  public final void setUp() {
+    injector1 = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+          filter("/*").through(TestFilter.class);
+          filter("*.html").through(TestFilter.class);
+          filter("/*").through(Key.get(TestFilter.class));
+          filter("*.jsp").through(Key.get(TestFilter.class));
+
+          // These filters should never fire
+          filter("/index/*").through(Key.get(NeverFilter.class));
+          filter("/public/login/*").through(Key.get(NeverFilter.class));
+      }
+    });
+
+    // Test second injector with exactly opposite pipeline config
+    injector2 = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+          // These filters should never fire
+          filter("*.html").through(NeverFilter.class);
+          filter("/non-jsp/*").through(Key.get(NeverFilter.class));
+
+          // only these filters fire.
+          filter("/index/*").through(Key.get(TestFilter.class));
+          filter("/public/login/*").through(Key.get(TestFilter.class));
+      }
+    });
+  }
+
+  @Override
+  public final void tearDown() {
+  }
+
+  public final void testDispatchThruInjectedGuiceFilter() throws ServletException, IOException {
+
+    //create mocks
+    FilterConfig filterConfig = createMock(FilterConfig.class);
+    ServletContext servletContext = createMock(ServletContext.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    FilterChain proceedingFilterChain = createMock(FilterChain.class);
+
+    //begin mock script ***
+
+    expect(filterConfig.getServletContext())
+        .andReturn(servletContext)
+        .once();
+
+    expect(request.getRequestURI())
+        .andReturn("/non-jsp/login.html") // use a path that will fail in injector2
+        .anyTimes();
+    expect(request.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //at the end, proceed down webapp's normal filter chain
+    proceedingFilterChain.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull());
+    expectLastCall().once();
+
+    //run mock script ***
+    replay(filterConfig, servletContext, request, proceedingFilterChain);
+
+    GuiceFilter webFilter = injector1.getInstance(GuiceFilter.class);
+
+    webFilter.init(filterConfig);
+    webFilter.doFilter(request, null, proceedingFilterChain);
+    webFilter.destroy();
+
+    //assert expectations
+    verify(filterConfig, servletContext, request, proceedingFilterChain);
+
+
+
+
+
+
+    // reset mocks and run them against the other injector
+    reset(filterConfig, servletContext, request, proceedingFilterChain);
+
+    // Create a second proceeding filter chain
+    FilterChain proceedingFilterChain2 = createMock(FilterChain.class);
+
+    //begin mock script ***
+
+    expect(filterConfig.getServletContext())
+        .andReturn(servletContext)
+        .once();
+    expect(request.getRequestURI())
+            .andReturn("/public/login/login.jsp") // use a path that will fail in injector1
+            .anyTimes();
+    expect(request.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //at the end, proceed down webapp's normal filter chain
+    proceedingFilterChain2.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull());
+    expectLastCall().once();
+
+    // Never fire on this pipeline
+    replay(filterConfig, servletContext, request, proceedingFilterChain2, proceedingFilterChain);
+
+    webFilter = injector2.getInstance(GuiceFilter.class);
+
+    webFilter.init(filterConfig);
+    webFilter.doFilter(request, null, proceedingFilterChain2);
+    webFilter.destroy();
+
+    // Verify that we have not crossed the streams, Venkman!
+    verify(filterConfig, servletContext, request, proceedingFilterChain, proceedingFilterChain2);
+  }
+
+  @Singleton
+  public static class TestFilter implements Filter {
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    public void destroy() {
+    }
+  }
+
+  @Singleton
+  public static class NeverFilter implements Filter {
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      fail("This filter should never have fired");
+    }
+
+    public void destroy() {
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java b/extensions/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java
new file mode 100644
index 0000000..689e3e8
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java
@@ -0,0 +1,101 @@
+package com.google.inject.servlet;
+
+import static org.easymock.EasyMock.createMock;
+
+import com.google.inject.Guice;
+import com.google.inject.Scopes;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+/**
+ * Ensures that an error is thrown if a Servlet or Filter is bound
+ * under any scope other than singleton, explicitly.
+ *
+ * @author dhanji@gmail.com
+ */
+public class InvalidScopeBindingTest extends TestCase {
+
+  @Override
+  protected void tearDown() throws Exception {
+    GuiceFilter.reset();
+  }
+
+  public final void testServletInNonSingletonScopeThrowsServletException(){
+    GuiceFilter guiceFilter = new GuiceFilter();
+
+    Guice.createInjector(new ServletModule() {
+      @Override
+      protected void configureServlets() {
+        serve("/*").with(MyNonSingletonServlet.class);
+      }
+    });
+
+    ServletException se = null;
+    try {
+      guiceFilter.init(createMock(FilterConfig.class));
+    } catch (ServletException e) {
+      se = e;
+    } finally {
+      assertNotNull("Servlet exception was not thrown with wrong scope binding", se);
+    }
+  }
+
+  public final void testFilterInNonSingletonScopeThrowsServletException(){
+    GuiceFilter guiceFilter = new GuiceFilter();
+
+    Guice.createInjector(new ServletModule() {
+      @Override
+      protected void configureServlets() {
+        filter("/*").through(MyNonSingletonFilter.class);
+      }
+    });
+
+    ServletException se = null;
+    try {
+      guiceFilter.init(createMock(FilterConfig.class));
+    } catch (ServletException e) {
+      se = e;
+    } finally {
+      assertNotNull("Servlet exception was not thrown with wrong scope binding", se);
+    }
+  }
+
+  public final void testHappyCaseFilter(){
+    GuiceFilter guiceFilter = new GuiceFilter();
+
+    Guice.createInjector(new ServletModule() {
+      @Override
+      protected void configureServlets() {
+        // Annotated scoping variant.
+        filter("/*").through(MySingletonFilter.class);
+
+        // Explicit scoping variant.
+        bind(DummyFilterImpl.class).in(Scopes.SINGLETON);
+        filter("/*").through(DummyFilterImpl.class);
+      }
+    });
+
+    ServletException se = null;
+    try {
+      guiceFilter.init(createMock(FilterConfig.class));
+    } catch (ServletException e) {
+      se = e;
+    } finally {
+      assertNull("Servlet exception was thrown with correct scope binding", se);
+    }
+  }
+
+  @RequestScoped
+  public static class MyNonSingletonServlet extends HttpServlet { }
+
+  @SessionScoped
+  public static class MyNonSingletonFilter extends DummyFilterImpl { }
+
+  @Singleton
+  public static class MySingletonFilter extends DummyFilterImpl { }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java b/extensions/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java
new file mode 100644
index 0000000..5fc285b
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java
@@ -0,0 +1,113 @@
+package com.google.inject.servlet;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *
+ * This tests that filter stage of the pipeline dispatches
+ * correctly to guice-managed filters with multiple modules.
+ *
+ * WARNING(dhanji): Non-parallelizable test =(
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class MultiModuleDispatchIntegrationTest extends TestCase {
+    private static int inits, doFilters, destroys;
+
+  @Override
+  public final void setUp() {
+    inits = 0;
+    doFilters = 0;
+    destroys = 0;
+
+    GuiceFilter.reset();
+  }
+
+
+  public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("/*").through(TestFilter.class);
+
+        // These filters should never fire
+        filter("*.jsp").through(Key.get(TestFilter.class));
+      }
+
+    }, new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("*.html").through(TestFilter.class);
+        filter("/*").through(Key.get(TestFilter.class));
+
+        // These filters should never fire
+        filter("/index/*").through(Key.get(TestFilter.class));
+      }
+
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+            .andReturn("/index.html")
+            .anyTimes();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not"
+        + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters
+        + "; destroys: " + destroys,
+        inits == 1 && doFilters == 3 && destroys == 1);
+  }
+
+  @Singleton
+  public static class TestFilter implements Filter {
+    public void init(FilterConfig filterConfig) throws ServletException {
+      inits++;
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      doFilters++;
+      filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/MultipleServletInjectorsTest.java b/extensions/servlet/test/com/google/inject/servlet/MultipleServletInjectorsTest.java
new file mode 100644
index 0000000..96dd51b
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/MultipleServletInjectorsTest.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import static com.google.inject.servlet.GuiceServletContextListener.INJECTOR_NAME;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import junit.framework.TestCase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.http.HttpServlet;
+
+/**
+ * This gorgeous test asserts that multiple servlet pipelines can
+ * run in the SAME JVM. booya.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class MultipleServletInjectorsTest extends TestCase {
+
+  private Injector injectorOne;
+  private Injector injectorTwo;
+
+  public final void testTwoInjectors() {
+    ServletContext fakeContextOne = createMock(ServletContext.class);
+    ServletContext fakeContextTwo = createMock(ServletContext.class);
+
+    fakeContextOne.setAttribute(eq(INJECTOR_NAME), isA(Injector.class));
+    expectLastCall().once();
+
+    fakeContextTwo.setAttribute(eq(INJECTOR_NAME), isA(Injector.class));
+    expectLastCall().once();
+
+    replay(fakeContextOne);
+
+    // Simulate the start of a servlet container.
+    new GuiceServletContextListener() {
+
+      @Override
+      protected Injector getInjector() {
+        // Cache this injector in the test for later testing...
+        return injectorOne = Guice.createInjector(new ServletModule() {
+
+          @Override
+          protected void configureServlets() {
+            // This creates a ManagedFilterPipeline internally...
+            serve("/*").with(DummyServlet.class);
+          }
+        });
+      }
+    }.contextInitialized(new ServletContextEvent(fakeContextOne));
+
+    ServletContext contextOne = injectorOne.getInstance(ServletContext.class);
+    assertNotNull(contextOne);
+
+    // Now simulate a second injector with a slightly different config.
+    replay(fakeContextTwo);
+    new GuiceServletContextListener() {
+
+      @Override
+      protected Injector getInjector() {
+        return injectorTwo = Guice.createInjector(new ServletModule() {
+
+          @Override
+          protected void configureServlets() {
+            // This creates a ManagedFilterPipeline internally...
+            filter("/8").through(DummyFilterImpl.class);
+
+            serve("/*").with(HttpServlet.class);
+          }
+        });
+      }
+    }.contextInitialized(new ServletContextEvent(fakeContextTwo));
+
+    ServletContext contextTwo = injectorTwo.getInstance(ServletContext.class);
+
+    // Make sure they are different.
+    assertNotNull(contextTwo);
+    assertNotSame(contextOne, contextTwo);
+
+    // Make sure they are as expected
+    assertSame(fakeContextOne, contextOne);
+    assertSame(fakeContextTwo, contextTwo);
+
+    // Make sure they are consistent.
+    assertSame(contextOne, injectorOne.getInstance(ServletContext.class));
+    assertSame(contextTwo, injectorTwo.getInstance(ServletContext.class));
+
+    verify(fakeContextOne, fakeContextTwo);
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ScopeRequestIntegrationTest.java b/extensions/servlet/test/com/google/inject/servlet/ScopeRequestIntegrationTest.java
new file mode 100644
index 0000000..9a4d0d4
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ScopeRequestIntegrationTest.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.OutOfScopeException;
+import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.ServletException;
+
+/**
+ * Tests continuation of requests
+ */
+
+public class ScopeRequestIntegrationTest extends TestCase {
+  private static final String A_VALUE = "thereaoskdao";
+  private static final String A_DIFFERENT_VALUE = "hiaoskd";
+
+  private static final String SHOULDNEVERBESEEN = "Shouldneverbeseen!";
+
+  public final void testNonHttpRequestScopedCallable()
+      throws ServletException, IOException, InterruptedException, ExecutionException {
+    ExecutorService executor = Executors.newSingleThreadExecutor();
+
+    // We use servlet module here because we want to test that @RequestScoped
+    // behaves properly with the non-HTTP request scope logic.
+    Injector injector = Guice.createInjector(new ServletModule() {
+      @Override protected void configureServlets() {
+        bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN);
+        bind(SomeObject.class).in(RequestScoped.class);
+      }
+    });
+
+    SomeObject someObject = new SomeObject(A_VALUE);
+    OffRequestCallable offRequestCallable = injector.getInstance(OffRequestCallable.class);
+    executor.submit(ServletScopes.scopeRequest(offRequestCallable,
+        ImmutableMap.<Key<?>, Object>of(Key.get(SomeObject.class), someObject))).get();
+
+    assertSame(injector.getInstance(OffRequestCallable.class), offRequestCallable);
+
+    // Make sure the value was passed on.
+    assertEquals(someObject.value, offRequestCallable.value);
+    assertFalse(SHOULDNEVERBESEEN.equals(someObject.value));
+
+    // Now create a new request and assert that the scopes don't cross.
+    someObject = new SomeObject(A_DIFFERENT_VALUE);
+    executor.submit(ServletScopes.scopeRequest(offRequestCallable,
+        ImmutableMap.<Key<?>, Object>of(Key.get(SomeObject.class), someObject))).get();
+
+    assertSame(injector.getInstance(OffRequestCallable.class), offRequestCallable);
+
+    // Make sure the value was passed on.
+    assertEquals(someObject.value, offRequestCallable.value);
+    assertFalse(SHOULDNEVERBESEEN.equals(someObject.value));
+    executor.shutdown();
+    executor.awaitTermination(2, TimeUnit.SECONDS);
+  }
+
+  public final void testWrongValueClasses() throws Exception {
+    Injector injector = Guice.createInjector(new ServletModule() {
+      @Override protected void configureServlets() {
+        bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN);
+        bind(SomeObject.class).in(RequestScoped.class);
+      }
+    });
+
+    OffRequestCallable offRequestCallable = injector.getInstance(OffRequestCallable.class);
+    try {
+      ServletScopes.scopeRequest(offRequestCallable,
+        ImmutableMap.<Key<?>, Object>of(Key.get(SomeObject.class), "Boo!"));
+      fail();
+    } catch(IllegalArgumentException iae) {
+      assertEquals("Value[Boo!] of type[java.lang.String] is not compatible with key[" + Key.get(SomeObject.class) + "]", iae.getMessage());
+    }
+  }
+
+  public final void testNullReplacement() throws Exception {
+    Injector injector = Guice.createInjector(new ServletModule() {
+      @Override protected void configureServlets() {
+        bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN);
+        bind(SomeObject.class).in(RequestScoped.class);
+      }
+    });
+
+    Callable<SomeObject> callable = injector.getInstance(Caller.class);
+    try {
+      assertNotNull(callable.call());
+      fail();
+    } catch(ProvisionException pe) {
+      assertTrue(pe.getCause() instanceof OutOfScopeException);
+    }
+
+    // Validate that an actual null entry in the map results in a null injected object.
+    Map<Key<?>, Object> map = Maps.newHashMap();
+    map.put(Key.get(SomeObject.class), null);
+    callable = ServletScopes.scopeRequest(injector.getInstance(Caller.class), map);
+    assertNull(callable.call());
+  }
+
+  @RequestScoped
+  public static class SomeObject {
+    private static final String INVALID = "invalid";
+
+    @Inject
+    public SomeObject(@Named(INVALID) String value) {
+      this.value = value;
+    }
+    private final String value;
+  }
+
+  @Singleton
+  public static class OffRequestCallable implements Callable<String> {
+    @Inject Provider<SomeObject> someObject;
+
+    public String value;
+
+    public String call() throws Exception {
+      // Inside this request, we should always get the same instance.
+      assertSame(someObject.get(), someObject.get());
+
+      value = someObject.get().value;
+      assertFalse(SHOULDNEVERBESEEN.equals(value));
+
+      return value;
+    }
+  }
+
+  private static class Caller implements Callable<SomeObject> {
+    @Inject Provider<SomeObject> someObject;
+
+    public SomeObject call() throws Exception {
+      return someObject.get();
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
new file mode 100644
index 0000000..c89834f
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
@@ -0,0 +1,308 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.spi.BindingScopingVisitor;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Ensures servlet spec compliance for CGI-style variables and general
+ *  path/pattern matching.
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail com)
+ */
+public class ServletDefinitionPathsTest extends TestCase {
+
+  // Data-driven test.
+  public final void testServletPathMatching() throws IOException, ServletException {
+    servletPath("/index.html", "*.html", "/index.html");
+    servletPath("/somewhere/index.html", "*.html", "/somewhere/index.html");
+    servletPath("/somewhere/index.html", "/*", "");
+    servletPath("/index.html", "/*", "");
+    servletPath("/", "/*", "");
+    servletPath("//", "/*", "");
+    servletPath("/////", "/*", "");
+    servletPath("", "/*", "");
+    servletPath("/thing/index.html", "/thing/*", "/thing");
+    servletPath("/thing/wing/index.html", "/thing/*", "/thing");
+  }
+
+  private void servletPath(final String requestPath, String mapping,
+      final String expectedServletPath) throws IOException, ServletException {
+
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    HttpServletResponse response = createMock(HttpServletResponse.class);
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(HttpServlet.class)))
+        .andReturn(binding);
+
+    final boolean[] run = new boolean[1];
+    //get an instance of this servlet
+    expect(injector.getInstance(Key.get(HttpServlet.class)))
+        .andReturn(new HttpServlet() {
+
+          @Override
+          protected void service(HttpServletRequest servletRequest,
+              HttpServletResponse httpServletResponse) throws ServletException, IOException {
+
+            final String path = servletRequest.getServletPath();
+            assertEquals(String.format("expected [%s] but was [%s]", expectedServletPath, path),
+                expectedServletPath, path);
+            run[0] = true;
+          }
+        });
+
+    expect(request.getServletPath())
+        .andReturn(requestPath);
+
+    replay(injector, binding, request);
+
+    ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
+        UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap<String, String>(), null);
+
+    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
+    servletDefinition.doService(request, response);
+
+    assertTrue("Servlet did not run!", run[0]);
+    
+    verify(injector, binding, request);
+
+  }
+
+  // Data-driven test.
+  public final void testPathInfoWithServletStyleMatching() throws IOException, ServletException {
+    pathInfoWithServletStyleMatching("/path/index.html", "/path", "/*", "/index.html", "");
+    pathInfoWithServletStyleMatching("/path//hulaboo///index.html", "/path", "/*",
+        "/hulaboo/index.html", "");
+    pathInfoWithServletStyleMatching("/path/", "/path", "/*", "/", "");
+    pathInfoWithServletStyleMatching("/path////////", "/path", "/*", "/", "");
+
+    // a servlet mapping of /thing/*
+    pathInfoWithServletStyleMatching("/path/thing////////", "/path", "/thing/*", "/", "/thing");
+    pathInfoWithServletStyleMatching("/path/thing/stuff", "/path", "/thing/*", "/stuff", "/thing");
+    pathInfoWithServletStyleMatching("/path/thing/stuff.html", "/path", "/thing/*", "/stuff.html",
+        "/thing");
+    pathInfoWithServletStyleMatching("/path/thing", "/path", "/thing/*", null, "/thing");
+
+    // see external issue 372
+    pathInfoWithServletStyleMatching("/path/some/path/of.jsp", "/path", "/thing/*",
+        null, "/some/path/of.jsp");
+
+    // *.xx style mapping
+    pathInfoWithServletStyleMatching("/path/thing.thing", "/path", "*.thing", null, "/thing.thing");
+    pathInfoWithServletStyleMatching("/path///h.thing", "/path", "*.thing", null, "/h.thing");
+    pathInfoWithServletStyleMatching("/path///...//h.thing", "/path", "*.thing", null,
+        "/.../h.thing");
+    pathInfoWithServletStyleMatching("/path/my/h.thing", "/path", "*.thing", null, "/my/h.thing");
+
+    // Encoded URLs
+    pathInfoWithServletStyleMatching("/path/index%2B.html", "/path", "/*", "/index+.html", "");
+    pathInfoWithServletStyleMatching("/path/a%20file%20with%20spaces%20in%20name.html", "/path", "/*", "/a file with spaces in name.html", "");
+    pathInfoWithServletStyleMatching("/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/*", "/Tamás nem más.html", "");
+  }
+
+  private void pathInfoWithServletStyleMatching(final String requestUri, final String contextPath,
+      String mapping, final String expectedPathInfo, final String servletPath)
+      throws IOException, ServletException {
+
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    HttpServletResponse response = createMock(HttpServletResponse.class);
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(HttpServlet.class)))
+        .andReturn(binding);
+
+    final boolean[] run = new boolean[1];
+    //get an instance of this servlet
+    expect(injector.getInstance(Key.get(HttpServlet.class)))
+        .andReturn(new HttpServlet() {
+
+          @Override
+          protected void service(HttpServletRequest servletRequest,
+              HttpServletResponse httpServletResponse) throws ServletException, IOException {
+
+            final String path = servletRequest.getPathInfo();
+
+            if (null == expectedPathInfo) {
+              assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
+                  path);
+            }
+            else {
+              assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
+                  expectedPathInfo, path);
+            }
+
+            //assert memoizer
+            //noinspection StringEquality
+            assertSame("memo field did not work", path, servletRequest.getPathInfo());
+
+            run[0] = true;
+          }
+        });
+
+    expect(request.getRequestURI())
+        .andReturn(requestUri);
+
+    expect(request.getServletPath())
+        .andReturn(servletPath)
+        .anyTimes();
+
+    expect(request.getContextPath())
+        .andReturn(contextPath);
+
+    expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null);
+
+    replay(injector, binding, request);
+
+    ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
+        UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap<String, String>(), null);
+
+    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
+    servletDefinition.doService(request, response);
+
+    assertTrue("Servlet did not run!", run[0]);
+
+    verify(injector, binding, request);
+  }
+
+  // Data-driven test.
+  public final void testPathInfoWithRegexMatching() throws IOException, ServletException {
+    // first a mapping of /*
+    pathInfoWithRegexMatching("/path/index.html", "/path", "/(.)*", "/index.html", "");
+    pathInfoWithRegexMatching("/path//hulaboo///index.html", "/path", "/(.)*",
+        "/hulaboo/index.html", "");
+    pathInfoWithRegexMatching("/path/", "/path", "/(.)*", "/", "");
+    pathInfoWithRegexMatching("/path////////", "/path", "/(.)*", "/", "");
+
+    // a servlet mapping of /thing/*
+    pathInfoWithRegexMatching("/path/thing////////", "/path", "/thing/(.)*", "/", "/thing");
+    pathInfoWithRegexMatching("/path/thing/stuff", "/path", "/thing/(.)*", "/stuff", "/thing");
+    pathInfoWithRegexMatching("/path/thing/stuff.html", "/path", "/thing/(.)*", "/stuff.html",
+        "/thing");
+    pathInfoWithRegexMatching("/path/thing", "/path", "/thing/(.)*", null, "/thing");
+
+    // *.xx style mapping
+    pathInfoWithRegexMatching("/path/thing.thing", "/path", ".*\\.thing", null, "/thing.thing");
+    pathInfoWithRegexMatching("/path///h.thing", "/path", ".*\\.thing", null, "/h.thing");
+    pathInfoWithRegexMatching("/path///...//h.thing", "/path", ".*\\.thing", null,
+        "/.../h.thing");
+    pathInfoWithRegexMatching("/path/my/h.thing", "/path", ".*\\.thing", null, "/my/h.thing");
+
+    // path
+    pathInfoWithRegexMatching("/path/test.com/com.test.MyServletModule", "", "/path/[^/]+/(.*)",
+        "com.test.MyServletModule", "/path/test.com/com.test.MyServletModule");
+
+    // Encoded URLs
+    pathInfoWithRegexMatching("/path/index%2B.html", "/path", "/(.)*", "/index+.html", "");
+    pathInfoWithRegexMatching("/path/a%20file%20with%20spaces%20in%20name.html", "/path", "/(.)*", "/a file with spaces in name.html", "");
+    pathInfoWithRegexMatching("/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/(.)*", "/Tamás nem más.html", "");
+  }
+
+  public final void pathInfoWithRegexMatching(final String requestUri, final String contextPath,
+      String mapping, final String expectedPathInfo, final String servletPath)
+      throws IOException, ServletException {
+
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    HttpServletResponse response = createMock(HttpServletResponse.class);
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(HttpServlet.class)))
+        .andReturn(binding);
+
+    final boolean[] run = new boolean[1];
+    //get an instance of this servlet
+    expect(injector.getInstance(Key.get(HttpServlet.class)))
+        .andReturn(new HttpServlet() {
+
+          @Override
+          protected void service(HttpServletRequest servletRequest,
+              HttpServletResponse httpServletResponse) throws ServletException, IOException {
+
+            final String path = servletRequest.getPathInfo();
+
+            if (null == expectedPathInfo) {
+              assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
+                  path);
+            }
+            else {
+              assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
+                  expectedPathInfo, path);
+            }
+
+            //assert memoizer
+            //noinspection StringEquality
+            assertSame("memo field did not work", path, servletRequest.getPathInfo());
+
+            run[0] = true;
+          }
+        });
+
+    expect(request.getRequestURI())
+        .andReturn(requestUri);
+
+    expect(request.getServletPath())
+        .andReturn(servletPath)
+        .anyTimes();
+
+    expect(request.getContextPath())
+        .andReturn(contextPath);
+
+    expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null);
+
+    replay(injector, binding, request);
+
+    ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
+        UriPatternType.get(UriPatternType.REGEX, mapping), new HashMap<String, String>(), null);
+
+    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
+    servletDefinition.doService(request, response);
+
+    assertTrue("Servlet did not run!", run[0]);
+    
+    verify(injector, binding, request);
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java
new file mode 100644
index 0000000..a6d52a2
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.spi.BindingScopingVisitor;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Enumeration;
+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;
+
+/**
+ * Basic unit test for lifecycle of a ServletDefinition (wrapper).
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail com)
+ */
+public class ServletDefinitionTest extends TestCase {
+
+  public final void testServletInitAndConfig() throws ServletException {
+    Injector injector = createMock(Injector.class);
+    Binding binding = createMock(Binding.class);
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(HttpServlet.class)))
+        .andReturn(binding);
+    final HttpServlet mockServlet = new HttpServlet() {
+    };
+    expect(injector.getInstance(Key.get(HttpServlet.class)))
+        .andReturn(mockServlet)
+        .anyTimes();
+
+    replay(injector, binding);
+
+    //some init params
+    //noinspection SSBasedInspection
+    final Map<String, String> initParams = new ImmutableMap.Builder<String, String>()
+      .put("ahsd", "asdas24dok")
+      .put("ahssd", "asdasd124ok").build();
+
+    String pattern = "/*";
+    final ServletDefinition servletDefinition = new ServletDefinition(pattern,
+        Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), initParams, null);
+
+    ServletContext servletContext = createMock(ServletContext.class);
+    final String contextName = "thing__!@@44__SRV" + getClass();
+    expect(servletContext.getServletContextName())
+        .andReturn(contextName);
+
+    replay(servletContext);
+
+    servletDefinition.init(servletContext, injector, Sets.<HttpServlet>newIdentityHashSet());
+
+    assertNotNull(mockServlet.getServletContext());
+    assertEquals(contextName, mockServlet.getServletContext().getServletContextName());
+    assertEquals(Key.get(HttpServlet.class).toString(), mockServlet.getServletName());
+
+    final ServletConfig servletConfig = mockServlet.getServletConfig();
+    final Enumeration names = servletConfig.getInitParameterNames();
+    while (names.hasMoreElements()) {
+      String name = (String) names.nextElement();
+
+      assertTrue(initParams.containsKey(name));
+      assertEquals(initParams.get(name), servletConfig.getInitParameter(name));
+    }
+
+    verify(injector, binding, servletContext);
+  }
+
+  public void testServiceWithContextPath() throws IOException, ServletException   {
+    String pattern = "/*";
+    //some init params
+    Map<String, String> initParams = new ImmutableMap.Builder<String, String>()
+        .put("ahsd", "asdas24dok")
+        .put("ahssd", "asdasd124ok")
+        .build();
+
+    final ServletDefinition servletDefinition = new ServletDefinition(pattern,
+        Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern),
+        initParams, null);
+    HttpServletResponse servletResponse = createMock(HttpServletResponse.class);
+    HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+
+    expect(servletRequest.getContextPath()).andReturn("/a_context_path");
+    expect(servletRequest.getRequestURI()).andReturn("/test.html");
+    replay(servletRequest, servletResponse);
+    servletDefinition.service(servletRequest, servletResponse);
+    verify(servletRequest, servletResponse);
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java
new file mode 100644
index 0000000..03edc59
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java
@@ -0,0 +1,344 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Tests the FilterPipeline that dispatches to guice-managed servlets,
+ * is a full integration test, with a real injector.
+ *
+ * @author Dhanji R. Prasanna (dhanji gmail com)
+ */
+public class ServletDispatchIntegrationTest extends TestCase {
+  private static int inits, services, destroys, doFilters;
+
+  @Override
+  public void setUp() {
+    inits = 0;
+    services = 0;
+    destroys = 0;
+    doFilters = 0;
+
+    GuiceFilter.reset();
+  }
+
+  public final void testDispatchRequestToManagedPipelineServlets()
+      throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        serve("/*").with(TestServlet.class);
+
+        // These servets should never fire... (ordering test)
+        serve("*.html").with(NeverServlet.class);
+        serve("/test/*").with(Key.get(NeverServlet.class));
+        serve("/index/*").with(Key.get(NeverServlet.class));
+        serve("*.jsp").with(Key.get(NeverServlet.class));
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+        .andReturn("/index.html")
+        .times(1);
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: "
+            + services + "; destroys: " + destroys,
+        inits == 2 && services == 1 && destroys == 2);
+  }
+
+  public final void testDispatchRequestToManagedPipelineWithFilter()
+      throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("/*").through(TestFilter.class);
+
+        serve("/*").with(TestServlet.class);
+
+        // These servets should never fire...
+        serve("*.html").with(NeverServlet.class);
+        serve("/test/*").with(Key.get(NeverServlet.class));
+        serve("/index/*").with(Key.get(NeverServlet.class));
+        serve("*.jsp").with(Key.get(NeverServlet.class));
+
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+        .andReturn("/index.html")
+        .times(2);
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: "
+            + services + "; destroys: " + destroys + "; doFilters: " + doFilters,
+        inits == 3 && services == 1 && destroys == 3 && doFilters == 1);
+  }
+
+  @Singleton
+  public static class TestServlet extends HttpServlet {
+    public void init(ServletConfig filterConfig) throws ServletException {
+      inits++;
+    }
+
+    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
+        throws IOException, ServletException {
+      services++;
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+
+  @Singleton
+  public static class NeverServlet extends HttpServlet {
+    public void init(ServletConfig filterConfig) throws ServletException {
+      inits++;
+    }
+
+    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
+        throws IOException, ServletException {
+      fail("NeverServlet was fired, when it should not have been.");
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+
+  @Singleton
+  public static class TestFilter implements Filter {
+    public void init(FilterConfig filterConfig) throws ServletException {
+      inits++;
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      doFilters++;
+      filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+
+
+  @Singleton
+  public static class ForwardingServlet extends HttpServlet {
+    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
+        throws IOException, ServletException {
+      final HttpServletRequest request = (HttpServletRequest) servletRequest;
+
+      request.getRequestDispatcher("/blah.jsp")
+          .forward(servletRequest, servletResponse);
+    }
+  }
+
+  @Singleton
+  public static class ForwardedServlet extends HttpServlet {
+    static int forwardedTo = 0;
+
+    // Reset for test.
+    public ForwardedServlet() {
+      forwardedTo = 0;
+    }
+
+    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
+        throws IOException, ServletException {
+      final HttpServletRequest request = (HttpServletRequest) servletRequest;
+
+      assertTrue((Boolean) request.getAttribute(REQUEST_DISPATCHER_REQUEST));
+      forwardedTo++;
+    }
+  }
+
+  public void testForwardUsingRequestDispatcher() throws IOException, ServletException {
+    Guice.createInjector(new ServletModule() {
+      @Override
+      protected void configureServlets() {
+        serve("/").with(ForwardingServlet.class);
+        serve("/blah.jsp").with(ForwardedServlet.class);
+      }
+    });
+
+    final HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+    HttpServletResponse responseMock = createMock(HttpServletResponse.class);
+    expect(requestMock.getRequestURI())
+        .andReturn("/")
+        .anyTimes();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true);
+    expect(requestMock.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(true);
+    requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST);
+
+    expect(responseMock.isCommitted()).andReturn(false);
+    responseMock.resetBuffer();
+
+    replay(requestMock, responseMock);
+
+    new GuiceFilter()
+        .doFilter(requestMock, responseMock,
+            createMock(FilterChain.class));
+
+    assertEquals("Incorrect number of forwards", 1, ForwardedServlet.forwardedTo);
+    verify(requestMock, responseMock);
+  }
+
+  public final void testQueryInRequestUri_regex() throws Exception {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filterRegex("(.)*\\.html").through(TestFilter.class);
+
+        serveRegex("(.)*\\.html").with(TestServlet.class);
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+        .andReturn("/index.html?query=params")
+        .atLeastOnce();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertEquals(1, doFilters);
+    assertEquals(1, services);
+  }
+
+  public final void testQueryInRequestUri() throws Exception {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("/index.html").through(TestFilter.class);
+
+        serve("/index.html").with(TestServlet.class);
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+        .andReturn("/index.html?query=params")
+        .atLeastOnce();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertEquals(1, doFilters);
+    assertEquals(1, services);
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletModuleTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletModuleTest.java
new file mode 100644
index 0000000..026f71e
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletModuleTest.java
@@ -0,0 +1,104 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Elements;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Tests for ServletModule, to ensure it captures bindings correctly.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class ServletModuleTest extends TestCase {
+  
+  public void testServletModuleCallOutsideConfigure() {
+    try {
+      new ServletModule() {{
+        serve("/*").with(DummyServlet.class);
+      }};
+      fail();
+    } catch (IllegalStateException e) {
+      // Expected.
+    }
+  }
+
+  public void testServletModuleReuse() {
+    Module module = new Module();
+    Elements.getElements(module); // use the module once (to, say, introspect bindings)
+    Injector injector = Guice.createInjector(module);  // use it again.
+    
+    Visitor visitor = new Visitor();    
+    // Validate only a single servlet binding & a single filter binding exist.
+    for(Binding<?> binding : injector.getAllBindings().values()) {
+      binding.acceptTargetVisitor(visitor);
+    }
+    assertEquals("wrong linked servlets: " + visitor.linkedServlets,
+        0, visitor.linkedServlets.size());
+    assertEquals("wrong linked filters: " + visitor.linkedFilters,
+        0, visitor.linkedFilters.size());
+    assertEquals("wrong instance servlets: " + visitor.instanceServlets,
+        1, visitor.instanceServlets.size());
+    assertEquals("wrong instance filters: " + visitor.instanceFilters,
+        1, visitor.instanceFilters.size());
+  }
+
+  private static class Module extends ServletModule {
+    @Override
+    protected void configureServlets() {
+      serve("/sam/*").with(new DummyServlet());
+      filter("/tara/*").through(new DummyFilterImpl());
+    }
+  }
+
+  private static class Visitor extends DefaultBindingTargetVisitor<Object, Void> implements
+      ServletModuleTargetVisitor<Object, Void> {
+    List<LinkedFilterBinding> linkedFilters = Lists.newArrayList();
+    List<LinkedServletBinding> linkedServlets = Lists.newArrayList();
+    List<InstanceFilterBinding> instanceFilters = Lists.newArrayList();
+    List<InstanceServletBinding> instanceServlets = Lists.newArrayList();
+    
+    public Void visit(LinkedFilterBinding binding) {
+      linkedFilters.add(binding);
+      return null;
+    }
+
+    public Void visit(InstanceFilterBinding binding) {
+      instanceFilters.add(binding);
+      return null;
+    }
+
+    public Void visit(LinkedServletBinding binding) {
+      linkedServlets.add(binding);
+      return null;
+    }
+
+    public Void visit(InstanceServletBinding binding) {
+      instanceServlets.add(binding);
+      return null;
+    }
+  }
+  
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
new file mode 100644
index 0000000..91abe9c
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
@@ -0,0 +1,315 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.BindingScopingVisitor;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.UUID;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Tests forwarding and inclusion (RequestDispatcher actions from the
+ * servlet spec).
+ *
+ * @author Dhanji R. Prasanna (dhanji@gmail com)
+ */
+public class ServletPipelineRequestDispatcherTest extends TestCase {
+  private static final Key<HttpServlet> HTTP_SERLVET_KEY = Key.get(HttpServlet.class);
+  private static final String A_KEY = "thinglyDEgintly" + new Date() + UUID.randomUUID();
+  private static final String A_VALUE = ServletPipelineRequestDispatcherTest.class.toString()
+      + new Date() + UUID.randomUUID();
+
+  public final void testIncludeManagedServlet() throws IOException, ServletException {
+    String pattern = "blah.html";
+    final ServletDefinition servletDefinition = new ServletDefinition(pattern,
+        Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern),
+        new HashMap<String, String>(), null);
+
+    final Injector injector = createMock(Injector.class);
+    final Binding binding = createMock(Binding.class);
+    final HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getAttribute(A_KEY))
+        .andReturn(A_VALUE);
+
+
+    requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true);
+    requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST);
+
+    final boolean[] run = new boolean[1];
+    final HttpServlet mockServlet = new HttpServlet() {
+      protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse)
+          throws ServletException, IOException {
+        run[0] = true;
+
+        final Object o = request.getAttribute(A_KEY);
+        assertEquals("Wrong attrib returned - " + o, A_VALUE, o);
+      }
+    };
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(HttpServlet.class)))
+        .andReturn(binding);
+    expect(injector.getInstance(HTTP_SERLVET_KEY))
+        .andReturn(mockServlet);
+
+
+    final Key<ServletDefinition> servetDefsKey = Key
+        .get(TypeLiteral.get(ServletDefinition.class));
+
+    Binding<ServletDefinition> mockBinding = createMock(Binding.class);
+    expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral())))
+        .andReturn(ImmutableList.<Binding<ServletDefinition>>of(mockBinding));
+    Provider<ServletDefinition> bindingProvider = Providers.of(servletDefinition);
+    expect(mockBinding.getProvider())
+        .andReturn(bindingProvider);
+
+    replay(injector, binding, requestMock, mockBinding);
+
+    // Have to init the Servlet before we can dispatch to it.
+    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
+
+    final RequestDispatcher dispatcher = new ManagedServletPipeline(
+        injector)
+        .getRequestDispatcher(pattern);
+
+    assertNotNull(dispatcher);
+    dispatcher.include(requestMock, createMock(HttpServletResponse.class));
+
+    assertTrue("Include did not dispatch to our servlet!", run[0]);
+
+    verify(injector, requestMock, mockBinding);
+  }
+
+  public final void testForwardToManagedServlet() throws IOException, ServletException {
+    String pattern = "blah.html";
+    final ServletDefinition servletDefinition = new ServletDefinition(pattern,
+        Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern),
+        new HashMap<String, String>(), null);
+
+    final Injector injector = createMock(Injector.class);
+    final Binding binding = createMock(Binding.class);
+    final HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+    final HttpServletResponse mockResponse = createMock(HttpServletResponse.class);
+
+    expect(requestMock.getAttribute(A_KEY))
+        .andReturn(A_VALUE);
+
+
+    requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true);
+    requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST);
+
+    expect(mockResponse.isCommitted())
+        .andReturn(false);
+
+    mockResponse.resetBuffer();
+    expectLastCall().once();
+
+    final List<String> paths = new ArrayList<String>();
+    final HttpServlet mockServlet = new HttpServlet() {
+      protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse)
+          throws ServletException, IOException {
+        paths.add(request.getRequestURI());
+
+        final Object o = request.getAttribute(A_KEY);
+        assertEquals("Wrong attrib returned - " + o, A_VALUE, o);
+      }
+    };
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(HttpServlet.class)))
+        .andReturn(binding);
+
+    expect(injector.getInstance(HTTP_SERLVET_KEY))
+        .andReturn(mockServlet);
+
+    final Key<ServletDefinition> servetDefsKey = Key
+        .get(TypeLiteral.get(ServletDefinition.class));
+
+    Binding<ServletDefinition> mockBinding = createMock(Binding.class);
+    expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral())))
+        .andReturn(ImmutableList.<Binding<ServletDefinition>>of(mockBinding));
+    Provider<ServletDefinition> bindingProvider = Providers.of(servletDefinition);
+    expect(mockBinding.getProvider())
+        .andReturn(bindingProvider);
+
+    replay(injector, binding, requestMock, mockResponse, mockBinding);
+
+    // Have to init the Servlet before we can dispatch to it.
+    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
+
+    final RequestDispatcher dispatcher = new ManagedServletPipeline(injector)
+        .getRequestDispatcher(pattern);
+
+    assertNotNull(dispatcher);
+    dispatcher.forward(requestMock, mockResponse);
+
+    assertTrue("Include did not dispatch to our servlet!", paths.contains(pattern));
+
+    verify(injector, requestMock, mockResponse, mockBinding);
+  }
+
+  public final void testForwardToManagedServletFailureOnCommittedBuffer()
+      throws IOException, ServletException {
+    IllegalStateException expected = null;
+    try {
+      forwardToManagedServletFailureOnCommittedBuffer();
+    }
+    catch (IllegalStateException ise) {
+      expected = ise;
+    } finally {
+      assertNotNull("Expected IllegalStateException was not thrown", expected);
+    }
+  }
+
+  public final void forwardToManagedServletFailureOnCommittedBuffer()
+      throws IOException, ServletException {
+    String pattern = "blah.html";
+    final ServletDefinition servletDefinition = new ServletDefinition(pattern,
+        Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern),
+        new HashMap<String, String>(), null);
+
+    final Injector injector = createMock(Injector.class);
+    final Binding binding = createMock(Binding.class);
+    final HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
+    final HttpServletResponse mockResponse = createMock(HttpServletResponse.class);
+
+    expect(mockResponse.isCommitted())
+        .andReturn(true);
+
+    final HttpServlet mockServlet = new HttpServlet() {
+      protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse)
+          throws ServletException, IOException {
+
+        final Object o = request.getAttribute(A_KEY);
+        assertEquals("Wrong attrib returned - " + o, A_VALUE, o);
+      }
+    };
+
+    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
+        .andReturn(true);
+    expect(injector.getBinding(Key.get(HttpServlet.class)))
+        .andReturn(binding);
+
+    expect(injector.getInstance(Key.get(HttpServlet.class)))
+        .andReturn(mockServlet);
+
+
+    final Key<ServletDefinition> servetDefsKey = Key
+        .get(TypeLiteral.get(ServletDefinition.class));
+
+    Binding<ServletDefinition> mockBinding = createMock(Binding.class);
+    expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral())))
+        .andReturn(ImmutableList.<Binding<ServletDefinition>>of(mockBinding));
+    Provider<ServletDefinition> bindingProvider = Providers.of(servletDefinition);
+    expect(mockBinding.getProvider())
+        .andReturn(bindingProvider);
+
+    replay(injector, binding, mockRequest, mockResponse, mockBinding);
+
+    // Have to init the Servlet before we can dispatch to it.
+    servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
+
+    final RequestDispatcher dispatcher = new ManagedServletPipeline(injector)
+        .getRequestDispatcher(pattern);
+
+    assertNotNull(dispatcher);
+
+    try {
+      dispatcher.forward(mockRequest, mockResponse);
+    }
+    finally {
+      verify(injector, mockRequest, mockResponse, mockBinding);
+    }
+  }
+
+  public final void testWrappedRequestUriAndUrlConsistency() {
+    final HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
+    expect(mockRequest.getScheme()).andReturn("http");
+    expect(mockRequest.getServerName()).andReturn("the.server");
+    expect(mockRequest.getServerPort()).andReturn(12345);
+    replay(mockRequest);
+    HttpServletRequest wrappedRequest = ManagedServletPipeline.wrapRequest(mockRequest, "/new-uri");
+    assertEquals("/new-uri", wrappedRequest.getRequestURI());
+    assertEquals("http://the.server:12345/new-uri", wrappedRequest.getRequestURL().toString());
+  }
+
+  public final void testWrappedRequestUrlNegativePort() {
+    final HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
+    expect(mockRequest.getScheme()).andReturn("http");
+    expect(mockRequest.getServerName()).andReturn("the.server");
+    expect(mockRequest.getServerPort()).andReturn(-1);
+    replay(mockRequest);
+    HttpServletRequest wrappedRequest = ManagedServletPipeline.wrapRequest(mockRequest, "/new-uri");
+    assertEquals("/new-uri", wrappedRequest.getRequestURI());
+    assertEquals("http://the.server/new-uri", wrappedRequest.getRequestURL().toString());
+  }
+
+  public final void testWrappedRequestUrlDefaultPort() {
+    final HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
+    expect(mockRequest.getScheme()).andReturn("http");
+    expect(mockRequest.getServerName()).andReturn("the.server");
+    expect(mockRequest.getServerPort()).andReturn(80);
+    replay(mockRequest);
+    HttpServletRequest wrappedRequest = ManagedServletPipeline.wrapRequest(mockRequest, "/new-uri");
+    assertEquals("/new-uri", wrappedRequest.getRequestURI());
+    assertEquals("http://the.server/new-uri", wrappedRequest.getRequestURL().toString());
+  }
+
+
+  public final void testWrappedRequestUrlDefaultHttpsPort() {
+    final HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
+    expect(mockRequest.getScheme()).andReturn("https");
+    expect(mockRequest.getServerName()).andReturn("the.server");
+    expect(mockRequest.getServerPort()).andReturn(443);
+    replay(mockRequest);
+    HttpServletRequest wrappedRequest = ManagedServletPipeline.wrapRequest(mockRequest, "/new-uri");
+    assertEquals("/new-uri", wrappedRequest.getRequestURI());
+    assertEquals("https://the.server/new-uri", wrappedRequest.getRequestURL().toString());
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletScopesTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletScopesTest.java
new file mode 100644
index 0000000..0ad40e3
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletScopesTest.java
@@ -0,0 +1,203 @@
+/**
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.servlet;
+
+import static com.google.inject.name.Names.named;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.PrivateModule;
+import com.google.inject.Provides;
+import com.google.inject.ScopeAnnotation;
+import com.google.inject.Scopes;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+import com.google.inject.spi.PrivateElements;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Tests for {@link ServletScopes}.
+ *
+ * @author forster@google.com (Mike Forster)
+ */
+public class ServletScopesTest extends TestCase {
+  public void testIsRequestScopedPositive() {
+    final Key<String> a = Key.get(String.class, named("A"));
+    final Key<String> b = Key.get(String.class, named("B"));
+    final Key<String> c = Key.get(String.class, named("C"));
+    final Key<String> d = Key.get(String.class, named("D"));
+    final Key<Object> e = Key.get(Object.class, named("E"));
+    final Key<String> f = Key.get(String.class, named("F"));
+    final Key<String> g = Key.get(String.class, named("G"));
+
+    Module requestScopedBindings = new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(a).to(b);
+        bind(b).to(c);
+        bind(c).toProvider(Providers.of("c")).in(ServletScopes.REQUEST);
+        bind(d).toProvider(Providers.of("d")).in(RequestScoped.class);
+        bind(e).to(AnnotatedRequestScopedClass.class);
+        install(new PrivateModule() {
+          @Override
+          protected void configure() {
+            bind(f).toProvider(Providers.of("f")).in(RequestScoped.class);
+            expose(f);
+          }
+        });
+      }
+
+      @Provides
+      @Named("G")
+      @RequestScoped
+      String provideG() {
+        return "g";
+      }
+    };
+
+    @SuppressWarnings("unchecked") // we know the module contains only bindings
+    List<Element> moduleBindings = Elements.getElements(requestScopedBindings);
+    ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings);
+    // linked bindings are not followed by modules
+    assertFalse(ServletScopes.isRequestScoped(map.get(a)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(b)));
+    assertTrue(ServletScopes.isRequestScoped(map.get(c)));
+    assertTrue(ServletScopes.isRequestScoped(map.get(d)));
+    // annotated classes are not followed by modules
+    assertFalse(ServletScopes.isRequestScoped(map.get(e)));
+    assertTrue(ServletScopes.isRequestScoped(map.get(f)));
+    assertTrue(ServletScopes.isRequestScoped(map.get(g)));
+
+    Injector injector = Guice.createInjector(requestScopedBindings, new ServletModule());
+    assertTrue(ServletScopes.isRequestScoped(injector.getBinding(a)));
+    assertTrue(ServletScopes.isRequestScoped(injector.getBinding(b)));
+    assertTrue(ServletScopes.isRequestScoped(injector.getBinding(c)));
+    assertTrue(ServletScopes.isRequestScoped(injector.getBinding(d)));
+    assertTrue(ServletScopes.isRequestScoped(injector.getBinding(e)));
+    assertTrue(ServletScopes.isRequestScoped(injector.getBinding(f)));
+    assertTrue(ServletScopes.isRequestScoped(injector.getBinding(g)));
+  }
+
+  public void testIsRequestScopedNegative() {
+    final Key<String> a = Key.get(String.class, named("A"));
+    final Key<String> b = Key.get(String.class, named("B"));
+    final Key<String> c = Key.get(String.class, named("C"));
+    final Key<String> d = Key.get(String.class, named("D"));
+    final Key<String> e = Key.get(String.class, named("E"));
+    final Key<String> f = Key.get(String.class, named("F"));
+    final Key<String> g = Key.get(String.class, named("G"));
+    final Key<String> h = Key.get(String.class, named("H"));
+    final Key<String> i = Key.get(String.class, named("I"));
+    final Key<String> j = Key.get(String.class, named("J"));
+
+    Module requestScopedBindings = new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(a).to(b);
+        bind(b).to(c);
+        bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE);
+        bind(d).toInstance("d");
+        bind(e).toProvider(Providers.of("e")).asEagerSingleton();
+        bind(f).toProvider(Providers.of("f")).in(Scopes.SINGLETON);
+        bind(g).toProvider(Providers.of("g")).in(Singleton.class);
+        bind(h).toProvider(Providers.of("h")).in(CustomScoped.class);
+        bindScope(CustomScoped.class, Scopes.NO_SCOPE);
+        install(new PrivateModule() {
+          @Override
+          protected void configure() {
+            bind(i).toProvider(Providers.of("i")).in(CustomScoped.class);
+            expose(i);
+          }
+        });
+      }
+
+      @Provides
+      @Named("J")
+      @CustomScoped
+      String provideJ() {
+        return "j";
+      }
+    };
+
+    @SuppressWarnings("unchecked") // we know the module contains only bindings
+    List<Element> moduleBindings = Elements.getElements(requestScopedBindings);
+    ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings);
+    assertFalse(ServletScopes.isRequestScoped(map.get(a)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(b)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(c)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(d)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(e)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(f)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(g)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(h)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(i)));
+    assertFalse(ServletScopes.isRequestScoped(map.get(j)));
+
+    Injector injector = Guice.createInjector(requestScopedBindings);
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(a)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(b)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(c)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(d)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(e)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(f)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(g)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(h)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(i)));
+    assertFalse(ServletScopes.isRequestScoped(injector.getBinding(j)));
+  }
+
+  @RequestScoped
+  static class AnnotatedRequestScopedClass {}
+
+  @Target({ ElementType.TYPE, ElementType.METHOD })
+  @Retention(RUNTIME)
+  @ScopeAnnotation
+  private @interface CustomScoped {}
+
+  private ImmutableMap<Key<?>, Binding<?>> indexBindings(Iterable<Element> elements) {
+    ImmutableMap.Builder<Key<?>, Binding<?>> builder = ImmutableMap.builder();
+    for (Element element : elements) {
+      if (element instanceof Binding) {
+        Binding<?> binding = (Binding<?>) element;
+        builder.put(binding.getKey(), binding);
+      } else if (element instanceof PrivateElements) {
+        PrivateElements privateElements = (PrivateElements) element;
+        Map<Key<?>, Binding<?>> privateBindings = indexBindings(privateElements.getElements());
+        for (Key<?> exposed : privateElements.getExposedKeys()) {
+          builder.put(exposed, privateBindings.get(exposed));
+        }
+      }
+    }
+    return builder.build();
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletSpiVisitor.java b/extensions/servlet/test/com/google/inject/servlet/ServletSpiVisitor.java
new file mode 100644
index 0000000..beff874
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletSpiVisitor.java
@@ -0,0 +1,152 @@
+/**
+ * Copyright (C) 2010 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.inject.servlet;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+
+import junit.framework.AssertionFailedError;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.servlet.Filter;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * A visitor for testing the servlet SPI extension.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+class ServletSpiVisitor
+    extends DefaultBindingTargetVisitor<Object, Integer>
+    implements ServletModuleTargetVisitor<Object, Integer> {
+
+  int otherCount = 0;
+  int currentCount = 0;
+  List<Params> actual = Lists.newArrayList();
+
+  /* The set of classes that are allowed to be "other" bindings. */
+  Set<Class> allowedClasses;
+
+  ServletSpiVisitor(boolean forInjector) {
+    ImmutableSet.Builder<Class> builder = ImmutableSet.builder();
+    // always ignore these things...
+    builder.add(ServletRequest.class,
+        ServletResponse.class, ManagedFilterPipeline.class, ManagedServletPipeline.class,
+        FilterPipeline.class, ServletContext.class, HttpServletRequest.class, Filter.class,
+        HttpServletResponse.class, HttpSession.class, Map.class, HttpServlet.class,
+        InternalServletModule.BackwardsCompatibleServletContextProvider.class,
+        GuiceFilter.class);
+    if(forInjector) {
+      // only ignore these if this is for the live injector, any other time it'd be an error!
+      builder.add(Injector.class, Stage.class, Logger.class);
+    }
+    this.allowedClasses = builder.build();
+  }
+
+  public Integer visit(InstanceFilterBinding binding) {
+    actual.add(new Params(binding, binding.getFilterInstance()));
+    return currentCount++;
+  }
+
+  public Integer visit(InstanceServletBinding binding) {
+    actual.add(new Params(binding, binding.getServletInstance()));
+    return currentCount++;
+  }
+
+  public Integer visit(LinkedFilterBinding binding) {
+    actual.add(new Params(binding, binding.getLinkedKey()));
+    return currentCount++;
+  }
+
+  public Integer visit(LinkedServletBinding binding) {
+    actual.add(new Params(binding, binding.getLinkedKey()));
+    return currentCount++;
+  }
+
+  @Override
+  protected Integer visitOther(Binding<? extends Object> binding) {
+    if(!allowedClasses.contains(binding.getKey().getTypeLiteral().getRawType())) {
+      throw new AssertionFailedError("invalid other binding: " + binding);
+    }
+    otherCount++;
+    return currentCount++;
+  }
+
+  static class Params {
+    private final String pattern;
+    private final Object keyOrInstance;
+    private final Map<String, String> params;
+    private final UriPatternType patternType;
+
+    Params(ServletModuleBinding binding, Object keyOrInstance) {
+      this.pattern = binding.getPattern();
+      this.keyOrInstance = keyOrInstance;
+      this.params = binding.getInitParams();
+      this.patternType = binding.getUriPatternType();
+    }
+
+    Params(String pattern, Object keyOrInstance, Map params, UriPatternType patternType) {
+      this.pattern = pattern;
+      this.keyOrInstance = keyOrInstance;
+      this.params = params;
+      this.patternType = patternType;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if(obj instanceof Params) {
+        Params o = (Params)obj;
+        return Objects.equal(pattern, o.pattern)
+            && Objects.equal(keyOrInstance, o.keyOrInstance)
+            && Objects.equal(params, o.params)
+            && Objects.equal(patternType, o.patternType);
+      } else {
+        return false;
+      }
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hashCode(pattern, keyOrInstance, params, patternType);
+    }
+
+    @Override
+    public String toString() {
+      return Objects.toStringHelper(Params.class)
+        .add("pattern", pattern)
+        .add("keyOrInstance", keyOrInstance)
+        .add("initParams", params)
+        .add("patternType", patternType)
+        .toString();
+    }
+  }
+}
\ No newline at end of file
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletTest.java
new file mode 100644
index 0000000..beb0873
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletTest.java
@@ -0,0 +1,471 @@
+/**
+ * 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 com.google.inject.servlet;
+
+import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.Asserts.reserialize;
+import static com.google.inject.servlet.ServletTestUtils.newFakeHttpServletRequest;
+import static com.google.inject.servlet.ServletTestUtils.newFakeHttpServletResponse;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.inject.AbstractModule;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+import com.google.inject.internal.Errors;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.servlet.ServletScopes.NullObject;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ServletTest extends TestCase {
+  private static final Key<HttpServletRequest> HTTP_REQ_KEY = Key.get(HttpServletRequest.class);
+  private static final Key<HttpServletResponse> HTTP_RESP_KEY = Key.get(HttpServletResponse.class);
+  private static final Key<Map<String, String[]>> REQ_PARAMS_KEY
+      = new Key<Map<String, String[]>>(RequestParameters.class) {};
+
+  private static final Key<InRequest> IN_REQUEST_NULL_KEY = Key.get(InRequest.class, Null.class);
+  private static final Key<InSession> IN_SESSION_KEY = Key.get(InSession.class);
+  private static final Key<InSession> IN_SESSION_NULL_KEY = Key.get(InSession.class, Null.class);
+
+  @Override
+  public void setUp() {
+    //we need to clear the reference to the pipeline every test =(
+    GuiceFilter.reset();
+  }
+  
+  public void testScopeExceptions() throws Exception {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        install(new ServletModule());        
+      }
+      @Provides @RequestScoped String provideString() { return "foo"; }
+      @Provides @SessionScoped Integer provideInteger() { return 1; }
+      @Provides @RequestScoped @Named("foo") String provideNamedString() { return "foo"; }
+    });
+    
+    try {
+      injector.getInstance(String.class);
+      fail();
+    } catch(ProvisionException oose) {
+      assertContains(oose.getMessage(), "Cannot access scoped [java.lang.String].");
+    }
+    
+    try {
+      injector.getInstance(Integer.class);
+      fail();
+    } catch(ProvisionException oose) {
+      assertContains(oose.getMessage(), "Cannot access scoped [java.lang.Integer].");
+    }
+    
+    Key<?> key = Key.get(String.class, Names.named("foo"));
+    try {
+      injector.getInstance(key);
+      fail();
+    } catch(ProvisionException oose) {
+      assertContains(oose.getMessage(), "Cannot access scoped [" + Errors.convert(key) + "]");
+    }
+  }
+
+  public void testRequestAndResponseBindings() throws Exception {
+    final Injector injector = createInjector();
+    final HttpServletRequest request = newFakeHttpServletRequest();
+    final HttpServletResponse response = newFakeHttpServletResponse();
+
+    final boolean[] invoked = new boolean[1];
+    GuiceFilter filter = new GuiceFilter();
+    FilterChain filterChain = new FilterChain() {
+      public void doFilter(ServletRequest servletRequest,
+          ServletResponse servletResponse) {
+        invoked[0] = true;
+        assertSame(request, servletRequest);
+        assertSame(request, injector.getInstance(ServletRequest.class));
+        assertSame(request, injector.getInstance(HTTP_REQ_KEY));
+
+        assertSame(response, servletResponse);
+        assertSame(response, injector.getInstance(ServletResponse.class));
+        assertSame(response, injector.getInstance(HTTP_RESP_KEY));
+
+        assertSame(servletRequest.getParameterMap(), injector.getInstance(REQ_PARAMS_KEY));
+      }
+    };
+    filter.doFilter(request, response, filterChain);
+
+    assertTrue(invoked[0]);
+  }
+
+  public void testRequestAndResponseBindings_wrappingFilter() throws Exception {
+    final HttpServletRequest request = newFakeHttpServletRequest();
+    final ImmutableMap<String, String[]> wrappedParamMap
+        = ImmutableMap.of("wrap", new String[]{"a", "b"});
+    final HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) {
+      @Override public Map getParameterMap() {
+        return wrappedParamMap;
+      }
+
+      @Override public Object getAttribute(String attr) {
+        // Ensure that attributes are stored on the original request object.
+        throw new UnsupportedOperationException();
+      }
+    };
+    final HttpServletResponse response = newFakeHttpServletResponse();
+    final HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response);
+
+    final boolean[] filterInvoked = new boolean[1];
+    final Injector injector = createInjector(new ServletModule() {
+      @Override protected void configureServlets() {
+        filter("/*").through(new Filter() {
+          @Inject Provider<ServletRequest> servletReqProvider;
+          @Inject Provider<HttpServletRequest> reqProvider;
+          @Inject Provider<ServletResponse> servletRespProvider;
+          @Inject Provider<HttpServletResponse> respProvider;
+
+          public void init(FilterConfig filterConfig) {}
+
+          public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
+              throws IOException, ServletException {
+            filterInvoked[0] = true;
+            assertSame(req, servletReqProvider.get());
+            assertSame(req, reqProvider.get());
+
+            assertSame(resp, servletRespProvider.get());
+            assertSame(resp, respProvider.get());
+
+            chain.doFilter(requestWrapper, responseWrapper);
+
+            assertSame(req, reqProvider.get());
+            assertSame(resp, respProvider.get());
+          }
+
+          public void destroy() {}
+        });
+      }
+    });
+
+    GuiceFilter filter = new GuiceFilter();
+    final boolean[] chainInvoked = new boolean[1];
+    FilterChain filterChain = new FilterChain() {
+      public void doFilter(ServletRequest servletRequest,
+          ServletResponse servletResponse) {
+        chainInvoked[0] = true;
+        assertSame(requestWrapper, servletRequest);
+        assertSame(requestWrapper, injector.getInstance(ServletRequest.class));
+        assertSame(requestWrapper, injector.getInstance(HTTP_REQ_KEY));
+
+        assertSame(responseWrapper, servletResponse);
+        assertSame(responseWrapper, injector.getInstance(ServletResponse.class));
+        assertSame(responseWrapper, injector.getInstance(HTTP_RESP_KEY));
+
+        assertSame(servletRequest.getParameterMap(), injector.getInstance(REQ_PARAMS_KEY));
+
+        InRequest inRequest = injector.getInstance(InRequest.class);
+        assertSame(inRequest, injector.getInstance(InRequest.class));
+      }
+    };
+    filter.doFilter(request, response, filterChain);
+
+    assertTrue(chainInvoked[0]);
+    assertTrue(filterInvoked[0]);
+  }
+
+  public void testRequestAndResponseBindings_matchesPassedParameters() throws Exception {
+    final int[] filterInvoked = new int[1];
+    final boolean[] servletInvoked = new boolean[1];
+    createInjector(new ServletModule() {
+      @Override protected void configureServlets() {
+        final HttpServletRequest[] previousReq = new HttpServletRequest[1];
+        final HttpServletResponse[] previousResp = new HttpServletResponse[1];
+
+        final Provider<ServletRequest> servletReqProvider = getProvider(ServletRequest.class);
+        final Provider<HttpServletRequest> reqProvider = getProvider(HttpServletRequest.class);
+        final Provider<ServletResponse> servletRespProvider = getProvider(ServletResponse.class);
+        final Provider<HttpServletResponse> respProvider = getProvider(HttpServletResponse.class);
+
+        Filter filter = new Filter() {
+          public void init(FilterConfig filterConfig) {}
+
+          public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
+              throws IOException, ServletException {
+            filterInvoked[0]++;
+            assertSame(req, servletReqProvider.get());
+            assertSame(req, reqProvider.get());
+            if (previousReq[0] != null) {
+              assertEquals(req, previousReq[0]);
+            }
+
+            assertSame(resp, servletRespProvider.get());
+            assertSame(resp, respProvider.get());
+            if (previousResp[0] != null) {
+              assertEquals(resp, previousResp[0]);
+            }
+
+            chain.doFilter(
+                previousReq[0] = new HttpServletRequestWrapper((HttpServletRequest) req),
+                previousResp[0] = new HttpServletResponseWrapper((HttpServletResponse) resp));
+
+            assertSame(req, reqProvider.get());
+            assertSame(resp, respProvider.get());
+          }
+
+          public void destroy() {}
+        };
+
+        filter("/*").through(filter);
+        filter("/*").through(filter);  // filter twice to test wrapping in filters
+        serve("/*").with(new HttpServlet() {
+          @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+            servletInvoked[0] = true;
+            assertSame(req, servletReqProvider.get());
+            assertSame(req, reqProvider.get());
+
+            assertSame(resp, servletRespProvider.get());
+            assertSame(resp, respProvider.get());
+          }
+        });
+      }
+    });
+
+    GuiceFilter filter = new GuiceFilter();
+    filter.doFilter(newFakeHttpServletRequest(), newFakeHttpServletResponse(), new FilterChain() {
+      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+        throw new IllegalStateException("Shouldn't get here");
+      }
+    });
+
+    assertEquals(2, filterInvoked[0]);
+    assertTrue(servletInvoked[0]);
+  }
+
+  public void testNewRequestObject()
+      throws CreationException, IOException, ServletException {
+    final Injector injector = createInjector();
+    final HttpServletRequest request = newFakeHttpServletRequest();
+
+    GuiceFilter filter = new GuiceFilter();
+    final boolean[] invoked = new boolean[1];
+    FilterChain filterChain = new FilterChain() {
+      public void doFilter(ServletRequest servletRequest,
+          ServletResponse servletResponse) {
+        invoked[0] = true;
+        assertNotNull(injector.getInstance(InRequest.class));
+        assertNull(injector.getInstance(IN_REQUEST_NULL_KEY));
+      }
+    };
+
+    filter.doFilter(request, null, filterChain);
+
+    assertTrue(invoked[0]);
+  }
+
+  public void testExistingRequestObject()
+      throws CreationException, IOException, ServletException {
+    final Injector injector = createInjector();
+    final HttpServletRequest request = newFakeHttpServletRequest();
+
+    GuiceFilter filter = new GuiceFilter();
+    final boolean[] invoked = new boolean[1];
+    FilterChain filterChain = new FilterChain() {
+      public void doFilter(ServletRequest servletRequest,
+          ServletResponse servletResponse) {
+        invoked[0] = true;
+
+        InRequest inRequest = injector.getInstance(InRequest.class);
+        assertSame(inRequest, injector.getInstance(InRequest.class));
+
+        assertNull(injector.getInstance(IN_REQUEST_NULL_KEY));
+        assertNull(injector.getInstance(IN_REQUEST_NULL_KEY));
+      }
+    };
+
+    filter.doFilter(request, null, filterChain);
+
+    assertTrue(invoked[0]);
+  }
+
+  public void testNewSessionObject()
+      throws CreationException, IOException, ServletException {
+    final Injector injector = createInjector();
+    final HttpServletRequest request = newFakeHttpServletRequest();
+
+    GuiceFilter filter = new GuiceFilter();
+    final boolean[] invoked = new boolean[1];
+    FilterChain filterChain = new FilterChain() {
+      public void doFilter(ServletRequest servletRequest,
+          ServletResponse servletResponse) {
+        invoked[0] = true;
+        assertNotNull(injector.getInstance(InSession.class));
+        assertNull(injector.getInstance(IN_SESSION_NULL_KEY));
+      }
+    };
+
+    filter.doFilter(request, null, filterChain);
+
+    assertTrue(invoked[0]);
+  }
+
+  public void testExistingSessionObject()
+      throws CreationException, IOException, ServletException {
+    final Injector injector = createInjector();
+    final HttpServletRequest request = newFakeHttpServletRequest();
+
+    GuiceFilter filter = new GuiceFilter();
+    final boolean[] invoked = new boolean[1];
+    FilterChain filterChain = new FilterChain() {
+      public void doFilter(ServletRequest servletRequest,
+          ServletResponse servletResponse) {
+        invoked[0] = true;
+
+        InSession inSession = injector.getInstance(InSession.class);
+        assertSame(inSession, injector.getInstance(InSession.class));
+
+        assertNull(injector.getInstance(IN_SESSION_NULL_KEY));
+        assertNull(injector.getInstance(IN_SESSION_NULL_KEY));
+      }
+    };
+
+    filter.doFilter(request, null, filterChain);
+
+    assertTrue(invoked[0]);
+  }
+
+  public void testHttpSessionIsSerializable() throws Exception {
+    final Injector injector = createInjector();
+    final HttpServletRequest request = newFakeHttpServletRequest();
+    final HttpSession session = request.getSession();
+
+    GuiceFilter filter = new GuiceFilter();
+    final boolean[] invoked = new boolean[1];
+    FilterChain filterChain = new FilterChain() {
+      public void doFilter(ServletRequest servletRequest,
+          ServletResponse servletResponse) {
+        invoked[0] = true;
+        assertNotNull(injector.getInstance(InSession.class));
+        assertNull(injector.getInstance(IN_SESSION_NULL_KEY));
+      }
+    };
+
+    filter.doFilter(request, null, filterChain);
+
+    assertTrue(invoked[0]);
+
+    HttpSession deserializedSession = reserialize(session);
+
+    String inSessionKey = IN_SESSION_KEY.toString();
+    String inSessionNullKey = IN_SESSION_NULL_KEY.toString();
+    assertTrue(deserializedSession.getAttribute(inSessionKey) instanceof InSession);
+    assertEquals(NullObject.INSTANCE, deserializedSession.getAttribute(inSessionNullKey));
+  }
+
+  public void testGuiceFilterConstructors() throws Exception {
+    final RuntimeException servletException = new RuntimeException();
+    final RuntimeException chainException = new RuntimeException();
+    final Injector injector = createInjector(new ServletModule() {
+      @Override protected void configureServlets() {
+        serve("/*").with(new HttpServlet() {
+          @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+            throw servletException;
+          }
+        });
+      }
+    });
+    final HttpServletRequest request = newFakeHttpServletRequest();
+    FilterChain filterChain = new FilterChain() {
+      public void doFilter(ServletRequest servletRequest,
+          ServletResponse servletResponse) {
+        throw chainException;
+      }
+    };
+
+    try {
+      new GuiceFilter().doFilter(request, null, filterChain);
+      fail();
+    } catch (RuntimeException e) {
+      assertSame(servletException, e);
+    }
+    try {
+      injector.getInstance(GuiceFilter.class).doFilter(request, null, filterChain);
+      fail();
+    } catch (RuntimeException e) {
+      assertSame(servletException, e);
+    }
+    try {
+      injector.getInstance(Key.get(GuiceFilter.class, ScopingOnly.class))
+          .doFilter(request, null, filterChain);
+      fail();
+    } catch (RuntimeException e) {
+      assertSame(chainException, e);
+    }
+  }
+
+  private Injector createInjector(Module... modules) throws CreationException {
+    return Guice.createInjector(Lists.<Module>asList(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new ServletModule());
+        bind(InSession.class);
+        bind(IN_SESSION_NULL_KEY).toProvider(Providers.<InSession>of(null)).in(SessionScoped.class);
+        bind(InRequest.class);
+        bind(IN_REQUEST_NULL_KEY).toProvider(Providers.<InRequest>of(null)).in(RequestScoped.class);
+      }
+    }, modules));
+  }
+
+  @SessionScoped
+  static class InSession implements Serializable {}
+
+  @RequestScoped
+  static class InRequest {}
+
+  @BindingAnnotation @Retention(RUNTIME) @Target({PARAMETER, METHOD, FIELD})
+  @interface Null {}
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletTestUtils.java b/extensions/servlet/test/com/google/inject/servlet/ServletTestUtils.java
new file mode 100644
index 0000000..e480541
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletTestUtils.java
@@ -0,0 +1,123 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package com.google.inject.servlet;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * Utilities for servlet tests.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class ServletTestUtils {
+  
+  private ServletTestUtils() {}
+
+  private static class ThrowingInvocationHandler implements InvocationHandler {
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+      throw new UnsupportedOperationException("No methods are supported on this object");
+    }
+  }
+  
+  /**
+   * Returns a FilterChain that does nothing.
+   */
+  public static FilterChain newNoOpFilterChain() {
+    return new FilterChain() {
+      public void doFilter(ServletRequest request, ServletResponse response) {
+      }
+    };
+  }
+  
+  /**
+   * Returns a fake, HttpServletRequest which stores attributes in a HashMap.
+   */
+  public static HttpServletRequest newFakeHttpServletRequest() {
+    HttpServletRequest delegate = (HttpServletRequest) Proxy.newProxyInstance(
+        HttpServletRequest.class.getClassLoader(),
+        new Class[] { HttpServletRequest.class }, new ThrowingInvocationHandler());
+    
+    return new HttpServletRequestWrapper(delegate) {
+      final Map<String, Object> attributes = Maps.newHashMap(); 
+      final HttpSession session = newFakeHttpSession();
+
+      @Override public String getMethod() {
+        return "GET";
+      }
+
+      @Override public Object getAttribute(String name) {
+        return attributes.get(name);
+      }
+      
+      @Override public void setAttribute(String name, Object value) {
+        attributes.put(name, value);
+      }
+      
+      @Override public Map getParameterMap() {
+        return ImmutableMap.of();
+      }
+      
+      @Override public String getRequestURI() {
+        return "/";
+      }
+      
+      @Override public String getContextPath() {
+        return "";
+      }
+      
+      @Override public HttpSession getSession() {
+        return session;
+      }
+    };
+  }
+  
+  /**
+   * Returns a fake, HttpServletResponse which throws an exception if any of its
+   * methods are called.
+   */
+  public static HttpServletResponse newFakeHttpServletResponse() {
+    return (HttpServletResponse) Proxy.newProxyInstance(
+        HttpServletResponse.class.getClassLoader(),
+        new Class[] { HttpServletResponse.class }, new ThrowingInvocationHandler());
+  }  
+  
+  private static class FakeHttpSessionHandler implements InvocationHandler, Serializable {
+    final Map<String, Object> attributes = Maps.newHashMap();
+
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+      String name = method.getName();
+      if ("setAttribute".equals(name)) {
+        attributes.put((String) args[0], args[1]);
+        return null;
+      } else if ("getAttribute".equals(name)) {
+        return attributes.get(args[0]);
+      } else {
+        throw new UnsupportedOperationException();
+      }
+    }
+  }
+
+  /**
+   * Returns a fake, serializable HttpSession which stores attributes in a HashMap.
+   */
+  public static HttpSession newFakeHttpSession() {
+    return (HttpSession) Proxy.newProxyInstance(HttpSession.class.getClassLoader(),
+        new Class[] { HttpSession.class }, new FakeHttpSessionHandler());
+  }
+
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletUtilsTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletUtilsTest.java
new file mode 100644
index 0000000..bd617ab
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletUtilsTest.java
@@ -0,0 +1,58 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.google.inject.servlet;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import junit.framework.TestCase;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Unit test for the servlet utility class.
+ *
+ * @author ntang@google.com (Michael Tang)
+ */
+public class ServletUtilsTest extends TestCase {
+  public void testGetContextRelativePath() {
+    HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+    expect(servletRequest.getContextPath()).andReturn("/a_context_path");
+    expect(servletRequest.getRequestURI()).andReturn("/a_context_path/test.html");
+    replay(servletRequest);
+    String path = ServletUtils.getContextRelativePath(servletRequest);
+    assertEquals("/test.html", path);
+    verify(servletRequest);
+  }
+
+  public void testGetContextRelativePathWithWrongPath() {
+    HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+    expect(servletRequest.getContextPath()).andReturn("/a_context_path");
+    expect(servletRequest.getRequestURI()).andReturn("/test.html");
+    replay(servletRequest);
+    String path = ServletUtils.getContextRelativePath(servletRequest);
+    assertNull(path);
+    verify(servletRequest);
+  }
+
+  public void testGetContextRelativePathWithRootPath() {
+    HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+    expect(servletRequest.getContextPath()).andReturn("/a_context_path");
+    expect(servletRequest.getRequestURI()).andReturn("/a_context_path");
+    replay(servletRequest);
+    String path = ServletUtils.getContextRelativePath(servletRequest);
+    assertEquals("/", path);
+    verify(servletRequest);
+  }
+
+  public void testGetContextRelativePathWithEmptyPath() {
+    HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+    expect(servletRequest.getContextPath()).andReturn("");
+    expect(servletRequest.getRequestURI()).andReturn("");
+    replay(servletRequest);
+    String path = ServletUtils.getContextRelativePath(servletRequest);
+    assertNull(path);
+    verify(servletRequest);
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/TransferRequestIntegrationTest.java b/extensions/servlet/test/com/google/inject/servlet/TransferRequestIntegrationTest.java
new file mode 100644
index 0000000..dbd18f7
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/TransferRequestIntegrationTest.java
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 2012 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.inject.servlet;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.OutOfScopeException;
+import com.google.inject.Provides;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+// TODO: Add test for HTTP transferring.
+/**
+ * Tests transferring of entire request scope.
+ */
+
+public class TransferRequestIntegrationTest extends TestCase {
+  private final Callable<Boolean> FALSE_CALLABLE = new Callable<Boolean>() {
+    @Override public Boolean call() {
+      return false;
+    }
+  };
+
+  public void testTransferHttp_outOfScope() {
+    try {
+      ServletScopes.transferRequest(FALSE_CALLABLE);
+      fail();
+    } catch (OutOfScopeException expected) {}
+  }
+
+  public void testTransferNonHttp_outOfScope() {
+    try {
+      ServletScopes.transferRequest(FALSE_CALLABLE);
+      fail();
+    } catch (OutOfScopeException expected) {}
+  }
+
+  public void testTransferNonHttpRequest() throws Exception {
+    final Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        bindScope(RequestScoped.class, ServletScopes.REQUEST);
+      }
+
+      @Provides @RequestScoped Object provideObject() {
+        return new Object();
+      }
+    });
+
+    Callable<Callable<Boolean>> callable = new Callable<Callable<Boolean>>() {
+      @Override public Callable<Boolean> call() {
+        final Object original = injector.getInstance(Object.class);
+        return ServletScopes.transferRequest(new Callable<Boolean>() {
+          @Override public Boolean call() {
+            return original == injector.getInstance(Object.class);
+          }
+        });
+      }
+    };
+
+    ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
+    Callable<Boolean> transfer = ServletScopes.scopeRequest(callable, seedMap).call();
+
+    ExecutorService executor = Executors.newSingleThreadExecutor();
+    assertTrue(executor.submit(transfer).get());
+    executor.shutdownNow();
+  }
+
+  public void testTransferNonHttpRequest_concurrentUseBlocks() throws Exception {
+    Callable<Boolean> callable = new Callable<Boolean>() {
+      @Override public Boolean call() throws Exception {
+        ExecutorService executor = Executors.newSingleThreadExecutor();
+        try {
+          Future<Boolean> future = executor.submit(ServletScopes.transferRequest(FALSE_CALLABLE));
+          try {
+            return future.get(100, TimeUnit.MILLISECONDS);
+          } catch (TimeoutException e) {
+            return true;
+          }
+        } finally {
+          executor.shutdownNow();
+        }
+      }
+    };
+
+    ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
+    assertTrue(ServletScopes.scopeRequest(callable, seedMap).call());
+  }
+
+  public void testTransferNonHttpRequest_concurrentUseSameThreadOk() throws Exception {
+    Callable<Boolean> callable = new Callable<Boolean>() {
+      @Override public Boolean call() throws Exception {
+        return ServletScopes.transferRequest(FALSE_CALLABLE).call();
+      }
+    };
+
+    ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
+    assertFalse(ServletScopes.scopeRequest(callable, seedMap).call());
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/UriPatternTypeTest.java b/extensions/servlet/test/com/google/inject/servlet/UriPatternTypeTest.java
new file mode 100644
index 0000000..5f82090
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/UriPatternTypeTest.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2014 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.inject.servlet;
+
+import junit.framework.TestCase;
+
+public class UriPatternTypeTest extends TestCase {
+
+  public void testMatches_servlet() {
+    UriPatternMatcher pattern = UriPatternType.get(UriPatternType.SERVLET, "/foo/*");
+    assertTrue(pattern.matches("/foo/asdf"));
+    assertTrue(pattern.matches("/foo/asdf?val=1"));
+    assertFalse(pattern.matches("/path/file.bar"));
+    assertFalse(pattern.matches("/path/file.bar?val=1"));
+    assertFalse(pattern.matches("/asdf"));
+    assertFalse(pattern.matches("/asdf?val=1"));
+
+    pattern = UriPatternType.get(UriPatternType.SERVLET, "*.bar");
+    assertFalse(pattern.matches("/foo/asdf"));
+    assertFalse(pattern.matches("/foo/asdf?val=1"));
+    assertTrue(pattern.matches("/path/file.bar"));
+    assertTrue(pattern.matches("/path/file.bar?val=1"));
+    assertFalse(pattern.matches("/asdf"));
+    assertFalse(pattern.matches("/asdf?val=1"));
+
+    pattern = UriPatternType.get(UriPatternType.SERVLET, "/asdf");
+    assertFalse(pattern.matches("/foo/asdf"));
+    assertFalse(pattern.matches("/foo/asdf?val=1"));
+    assertFalse(pattern.matches("/path/file.bar"));
+    assertFalse(pattern.matches("/path/file.bar?val=1"));
+    assertTrue(pattern.matches("/asdf"));
+    assertTrue(pattern.matches("/asdf?val=1"));
+  }
+
+  public void testMatches_regex() {
+    UriPatternMatcher pattern = UriPatternType.get(UriPatternType.REGEX, "/.*/foo");
+    assertFalse(pattern.matches("/foo/asdf"));
+    assertFalse(pattern.matches("/foo/asdf?val=1"));
+    assertTrue(pattern.matches("/path/foo"));
+    assertTrue(pattern.matches("/path/foo?val=1"));
+    assertFalse(pattern.matches("/foo"));
+    assertFalse(pattern.matches("/foo?val=1"));
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java b/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java
new file mode 100644
index 0000000..ad55230
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java
@@ -0,0 +1,182 @@
+package com.google.inject.servlet;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *
+ * This tests that filter stage of the pipeline dispatches
+ * correctly to guice-managed filters.
+ *
+ * WARNING(dhanji): Non-parallelizable test =(
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public class VarargsFilterDispatchIntegrationTest extends TestCase {
+    private static int inits, doFilters, destroys;
+
+  @Override
+  public final void setUp() {
+    inits = 0;
+    doFilters = 0;
+    destroys = 0;
+
+    GuiceFilter.reset();
+  }
+
+
+  public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        // This is actually a double match for "/*"
+        filter("/*", "*.html", "/*").through(Key.get(TestFilter.class));
+
+        // These filters should never fire
+        filter("/index/*").through(Key.get(TestFilter.class));
+        filter("*.jsp").through(Key.get(TestFilter.class));
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+            .andReturn("/index.html")
+            .anyTimes();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not"
+        + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters
+        + "; destroys: " + destroys,
+        inits == 1 && doFilters == 3 && destroys == 1);
+  }
+
+  public final void testDispatchThatNoFiltersFire() throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("/public/*", "*.html", "*.xml").through(Key.get(TestFilter.class));
+
+        // These filters should never fire
+        filter("/index/*").through(Key.get(TestFilter.class));
+        filter("*.jsp").through(Key.get(TestFilter.class));
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+            .andReturn("/index.xhtml")
+            .anyTimes();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not "
+        + "fire correct number of times-- inits: " + inits + "; dos: " + doFilters
+        + "; destroys: " + destroys,
+        inits == 1 && doFilters == 0 && destroys == 1);
+  }
+
+  public final void testDispatchFilterPipelineWithRegexMatching() throws ServletException,
+      IOException {
+
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filterRegex("/[A-Za-z]*", "/index").through(TestFilter.class);
+
+        //these filters should never fire
+        filterRegex("\\w").through(Key.get(TestFilter.class));
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+            .andReturn("/index")
+            .anyTimes();
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not fire "
+        + "correct number of times-- inits: " + inits + "; dos: " + doFilters
+        + "; destroys: " + destroys,
+        inits == 1 && doFilters == 2 && destroys == 1);
+  }
+
+  @Singleton
+  public static class TestFilter implements Filter {
+    public void init(FilterConfig filterConfig) throws ServletException {
+      inits++;
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      doFilters++;
+      filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+}
diff --git a/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java b/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java
new file mode 100644
index 0000000..2309904
--- /dev/null
+++ b/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java
@@ -0,0 +1,234 @@
+/**
+ * Copyright (C) 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.inject.servlet;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Tests the FilterPipeline that dispatches to guice-managed servlets,
+ * is a full integration test, with a real injector.
+ *
+ * @author Dhanji R. Prasanna (dhanji gmail com)
+ */
+public class VarargsServletDispatchIntegrationTest extends TestCase {
+  private static int inits, services, destroys, doFilters;
+
+  @Override
+  public void setUp() {
+    inits = 0;
+    services = 0;
+    destroys = 0;
+    doFilters = 0;
+
+    GuiceFilter.reset();
+  }
+
+  public final void testDispatchRequestToManagedPipelineServlets()
+      throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        serve("/*", "/index.html").with(TestServlet.class);
+
+        // These servets should never fire... (ordering test)
+        serve("*.html", "/o/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class));
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+        .andReturn("/index.html")
+        .times(1);
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: "
+            + services + "; destroys: " + destroys,
+        inits == 2 && services == 1 && destroys == 2);
+  }
+
+  public final void testVarargsSkipDispatchRequestToManagedPipelineServlets()
+      throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        serve("/notindex", "/&*", "/index.html").with(TestServlet.class);
+
+        // These servets should never fire... (ordering test)
+        serve("*.html", "/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class));
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+        .andReturn("/index.html")
+        .times(3);
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: "
+            + services + "; destroys: " + destroys,
+        inits == 2 && services == 1 && destroys == 2);
+  }
+
+  public final void testDispatchRequestToManagedPipelineWithFilter()
+      throws ServletException, IOException {
+    final Injector injector = Guice.createInjector(new ServletModule() {
+
+      @Override
+      protected void configureServlets() {
+        filter("/*").through(TestFilter.class);
+
+        serve("/*").with(TestServlet.class);
+
+        // These servets should never fire...
+        serve("*.html", "/y/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class));
+
+      }
+    });
+
+    final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class);
+
+    pipeline.initPipeline(null);
+
+    //create ourselves a mock request with test URI
+    HttpServletRequest requestMock = createMock(HttpServletRequest.class);
+
+    expect(requestMock.getRequestURI())
+        .andReturn("/index.html")
+        .times(2);
+    expect(requestMock.getContextPath())
+        .andReturn("")
+        .anyTimes();
+
+    //dispatch request
+    replay(requestMock);
+
+    pipeline.dispatch(requestMock, null, createMock(FilterChain.class));
+
+    pipeline.destroyPipeline();
+
+    verify(requestMock);
+
+    assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: "
+            + services + "; destroys: " + destroys,
+        inits == 3 && services == 1 && destroys == 3 && doFilters == 1);
+  }
+
+  @Singleton
+  public static class TestServlet extends HttpServlet {
+    public void init(ServletConfig filterConfig) throws ServletException {
+      inits++;
+    }
+
+    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
+        throws IOException, ServletException {
+      services++;
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+
+  @Singleton
+  public static class NeverServlet extends HttpServlet {
+    public void init(ServletConfig filterConfig) throws ServletException {
+      inits++;
+    }
+
+    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
+        throws IOException, ServletException {
+      fail("NeverServlet was fired, when it should not have been.");
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+
+  @Singleton
+  public static class TestFilter implements Filter {
+    public void init(FilterConfig filterConfig) throws ServletException {
+      inits++;
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+        FilterChain filterChain) throws IOException, ServletException {
+      doFilters++;
+      filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    public void destroy() {
+      destroys++;
+    }
+  }
+}
diff --git a/extensions/spring/.gitignore b/extensions/spring/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/extensions/spring/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/extensions/spring/build.properties b/extensions/spring/build.properties
new file mode 100644
index 0000000..9108597
--- /dev/null
+++ b/extensions/spring/build.properties
@@ -0,0 +1,7 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.spring.SpringTest
+module=com.google.inject.spring
+fragment=true
diff --git a/extensions/spring/build.xml b/extensions/spring/build.xml
new file mode 100644
index 0000000..2d708a6
--- /dev/null
+++ b/extensions/spring/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-spring" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/spring/pom.xml b/extensions/spring/pom.xml
new file mode 100644
index 0000000..5501a53
--- /dev/null
+++ b/extensions/spring/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-spring</artifactId>
+
+  <name>Google Guice - Extensions - Spring</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
+      <version>3.0.5.RELEASE</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/extensions/spring/src/com/google/inject/spring/SpringIntegration.java b/extensions/spring/src/com/google/inject/spring/SpringIntegration.java
new file mode 100644
index 0000000..fd3d0fd
--- /dev/null
+++ b/extensions/spring/src/com/google/inject/spring/SpringIntegration.java
@@ -0,0 +1,136 @@
+/**
+ * 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 com.google.inject.spring;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Binder;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.name.Names;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.ListableBeanFactory;
+
+/**
+ * Integrates Guice with Spring.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class SpringIntegration {
+  private SpringIntegration() {}
+
+  /**
+   * Creates a provider which looks up objects from Spring using the given name.
+   * Expects a binding to {@link
+   * org.springframework.beans.factory.BeanFactory}. Example usage:
+   *
+   * <pre>
+   * bind(DataSource.class)
+   *   .toProvider(fromSpring(DataSource.class, "dataSource"));
+   * </pre>
+   */
+  public static <T> Provider<T> fromSpring(Class<T> type, String name) {
+    return new InjectableSpringProvider<T>(type, name);
+  }
+
+  /**
+   * Binds all Spring beans from the given factory by name. For a Spring bean
+   * named "foo", this method creates a binding to the bean's type and
+   * {@code @Named("foo")}.
+   *
+   * @see com.google.inject.name.Named
+   * @see com.google.inject.name.Names#named(String) 
+   */
+  public static void bindAll(Binder binder, ListableBeanFactory beanFactory) {
+    binder = binder.skipSources(SpringIntegration.class);
+
+    for (String name : beanFactory.getBeanDefinitionNames()) {
+      Class<?> type = beanFactory.getType(name);
+      bindBean(binder, beanFactory, name, type);
+    }
+  }
+
+  static <T> void bindBean(Binder binder, ListableBeanFactory beanFactory,
+      String name, Class<T> type) {
+    SpringProvider<T> provider
+        = SpringProvider.newInstance(type, name);
+    try {
+      provider.initialize(beanFactory);
+    }
+    catch (Exception e) {
+      binder.addError(e);
+      return;
+    }
+
+    binder.bind(type)
+        .annotatedWith(Names.named(name))
+        .toProvider(provider);
+  }
+
+  static class SpringProvider<T> implements Provider<T> {
+
+    BeanFactory beanFactory;
+    boolean singleton;
+    final Class<T> type;
+    final String name;
+
+    public SpringProvider(Class<T> type, String name) {
+      this.type = checkNotNull(type, "type");
+      this.name = checkNotNull(name, "name");
+    }
+
+    static <T> SpringProvider<T> newInstance(Class<T> type, String name) {
+      return new SpringProvider<T>(type, name);
+    }
+
+    void initialize(BeanFactory beanFactory) {
+      this.beanFactory = beanFactory;
+      if (!beanFactory.isTypeMatch(name, type)) {
+        throw new ClassCastException("Spring bean named '" + name
+            + "' does not implement " + type.getName() + ".");
+      }
+      singleton = beanFactory.isSingleton(name);
+    }
+
+    public T get() {
+      return singleton ? getSingleton() : type.cast(beanFactory.getBean(name));
+    }
+
+    volatile T instance;
+
+    private T getSingleton() {
+      if (instance == null) {
+        instance = type.cast(beanFactory.getBean(name));
+      }
+      return instance;
+    }
+  }
+
+  static class InjectableSpringProvider<T> extends SpringProvider<T> {
+
+    InjectableSpringProvider(Class<T> type, String name) {
+      super(type, name);
+    }
+
+    @Inject
+    @Override
+    void initialize(BeanFactory beanFactory) {
+      super.initialize(beanFactory);
+    }
+  }
+}
diff --git a/extensions/spring/src/com/google/inject/spring/package-info.java b/extensions/spring/src/com/google/inject/spring/package-info.java
new file mode 100644
index 0000000..42ca1c2
--- /dev/null
+++ b/extensions/spring/src/com/google/inject/spring/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Spring integration; this extension requires {@code guice-spring.jar}.
+ */
+package com.google.inject.spring;
diff --git a/extensions/spring/test/com/google/inject/spring/SpringIntegrationTest.java b/extensions/spring/test/com/google/inject/spring/SpringIntegrationTest.java
new file mode 100644
index 0000000..7f9c983
--- /dev/null
+++ b/extensions/spring/test/com/google/inject/spring/SpringIntegrationTest.java
@@ -0,0 +1,104 @@
+/**
+ * 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 com.google.inject.spring;
+
+import static com.google.inject.spring.SpringIntegration.fromSpring;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class SpringIntegrationTest extends TestCase {
+
+  public void testBindFromSpring() throws CreationException {
+    final DefaultListableBeanFactory beanFactory
+        = new DefaultListableBeanFactory();
+
+    RootBeanDefinition singleton
+        = new RootBeanDefinition(Singleton.class);
+    beanFactory.registerBeanDefinition("singleton", singleton);
+
+    RootBeanDefinition prototype
+        = new RootBeanDefinition(Prototype.class, false);
+    beanFactory.registerBeanDefinition("prototype", prototype);
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(BeanFactory.class).toInstance(beanFactory);
+        bind(Singleton.class)
+            .toProvider(fromSpring(Singleton.class, "singleton"));
+        bind(Prototype.class)
+            .toProvider(fromSpring(Prototype.class, "prototype"));
+      }
+    });
+
+    assertNotNull(injector.getInstance(Singleton.class));
+    assertSame(injector.getInstance(Singleton.class),
+        injector.getInstance(Singleton.class));
+
+    assertNotNull(injector.getInstance(Prototype.class));
+    assertNotSame(injector.getInstance(Prototype.class),
+        injector.getInstance(Prototype.class));
+  }
+
+  public void testBindAll() throws CreationException {
+    final DefaultListableBeanFactory beanFactory
+        = new DefaultListableBeanFactory();
+
+    RootBeanDefinition singleton
+        = new RootBeanDefinition(Singleton.class);
+    beanFactory.registerBeanDefinition("singleton", singleton);
+
+    RootBeanDefinition prototype
+        = new RootBeanDefinition(Prototype.class, false);
+    beanFactory.registerBeanDefinition("prototype", prototype);
+
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        SpringIntegration.bindAll(binder(), beanFactory);
+      }
+    });
+
+    Key<Singleton> singletonKey
+        = Key.get(Singleton.class, Names.named("singleton"));
+    Key<Prototype> prototypeKey
+        = Key.get(Prototype.class, Names.named("prototype"));
+
+    assertNotNull(injector.getInstance(singletonKey));
+    assertSame(injector.getInstance(singletonKey),
+        injector.getInstance(singletonKey));
+
+    assertNotNull(injector.getInstance(prototypeKey));
+    assertNotSame(injector.getInstance(prototypeKey),
+        injector.getInstance(prototypeKey));
+  }
+
+  static class Singleton {}
+  static class Prototype {}
+}
diff --git a/extensions/struts2/.gitignore b/extensions/struts2/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/extensions/struts2/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/extensions/struts2/build.properties b/extensions/struts2/build.properties
new file mode 100644
index 0000000..e2c753b
--- /dev/null
+++ b/extensions/struts2/build.properties
@@ -0,0 +1,7 @@
+lib.dir=../../lib
+ext.lib.dir=lib
+src.dir=src
+test.dir=test
+build.dir=build
+module=com.google.inject.struts2
+fragment=true
diff --git a/extensions/struts2/build.xml b/extensions/struts2/build.xml
new file mode 100644
index 0000000..e105372
--- /dev/null
+++ b/extensions/struts2/build.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+
+<project name="guice-struts2-plugin" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+  	<fileset dir="${ext.lib.dir}" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+    <fileset dir="../servlet/build" includes="*.jar"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/struts2/example/build.properties b/extensions/struts2/example/build.properties
new file mode 100644
index 0000000..a155282
--- /dev/null
+++ b/extensions/struts2/example/build.properties
@@ -0,0 +1,3 @@
+lib.dir=../lib
+src.dir=src
+build.dir=build
diff --git a/extensions/struts2/example/build.xml b/extensions/struts2/example/build.xml
new file mode 100644
index 0000000..8ebb1fe
--- /dev/null
+++ b/extensions/struts2/example/build.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+
+<project name="guice-struts2-example">
+
+  <import file="../../common.xml"/>
+  
+  <property file="build.properties"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="../../build/dist" includes="*.jar"/>
+  </path>
+
+</project>
diff --git a/extensions/struts2/example/root/Counter.jsp b/extensions/struts2/example/root/Counter.jsp
new file mode 100644
index 0000000..1e7f9c4
--- /dev/null
+++ b/extensions/struts2/example/root/Counter.jsp
@@ -0,0 +1,15 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+<html>
+  <body>
+    <h1>Counter Example</h1>
+    <h3><b>Hits in this session:</b>
+      <s:property value="count"/></h3>
+
+    <h3><b>Status:</b>
+      <s:property value="status"/></h3>
+
+    <h3><b>Message:</b>
+      <s:property value="message"/></h3>
+  </body>
+</html>
diff --git a/extensions/struts2/example/root/WEB-INF/web.xml b/extensions/struts2/example/root/WEB-INF/web.xml
new file mode 100644
index 0000000..ca48034
--- /dev/null
+++ b/extensions/struts2/example/root/WEB-INF/web.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+  "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+
+  <listener>
+      <listener-class>com.google.inject.struts2.example.ExampleListener</listener-class>
+  </listener>  
+
+  <filter>
+    <filter-name>guice</filter-name>
+    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
+  </filter>
+
+  <filter-mapping>
+    <filter-name>guice</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+</web-app>
diff --git a/extensions/struts2/example/src/com/google/inject/struts2/example/Count.java b/extensions/struts2/example/src/com/google/inject/struts2/example/Count.java
new file mode 100644
index 0000000..76e7ec9
--- /dev/null
+++ b/extensions/struts2/example/src/com/google/inject/struts2/example/Count.java
@@ -0,0 +1,53 @@
+/**
+ * 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 com.google.inject.struts2.example;
+
+import com.google.inject.Inject;
+import static com.opensymphony.xwork2.Action.SUCCESS;
+
+public class Count {
+
+  final Counter counter;
+  final Service service;
+  String message;
+
+  @Inject
+  public Count(Counter counter, Service service) {
+    this.counter = counter;
+    this.service = service;
+  }
+
+  public String execute() {
+    return SUCCESS;
+  }
+
+  public int getCount() {
+    return counter.increment();
+  }
+
+  public String getStatus() {
+    return service.getStatus();
+  }
+
+  public String getMessage() {
+    return message;
+  }
+
+  public void setMessage(String message) {
+    this.message = message;
+  }
+}
diff --git a/extensions/struts2/example/src/com/google/inject/struts2/example/Counter.java b/extensions/struts2/example/src/com/google/inject/struts2/example/Counter.java
new file mode 100644
index 0000000..c375b98
--- /dev/null
+++ b/extensions/struts2/example/src/com/google/inject/struts2/example/Counter.java
@@ -0,0 +1,33 @@
+/**
+ * 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 com.google.inject.struts2.example;
+
+import com.google.inject.servlet.SessionScoped;
+
+/**
+ * Session-scoped counter.
+ */
+@SessionScoped
+public class Counter {
+
+  int count = 0;
+
+  /** Increments the count and returns the new value. */
+  public synchronized int increment() {
+    return count++;
+  }
+}
diff --git a/extensions/struts2/example/src/com/google/inject/struts2/example/ExampleListener.java b/extensions/struts2/example/src/com/google/inject/struts2/example/ExampleListener.java
new file mode 100644
index 0000000..244d34b
--- /dev/null
+++ b/extensions/struts2/example/src/com/google/inject/struts2/example/ExampleListener.java
@@ -0,0 +1,51 @@
+/**
+ * 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 com.google.inject.struts2.example;
+
+import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+import com.google.inject.struts2.Struts2GuicePluginModule;
+
+/**
+ * Example application module.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ExampleListener extends GuiceServletContextListener {
+
+  public Injector getInjector() {
+    return Guice.createInjector(
+      new Struts2GuicePluginModule(),
+      new ServletModule() {
+        @Override
+        protected void configureServlets() {      
+          // Struts 2 setup
+          bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class);
+          filter("/*").through(StrutsPrepareAndExecuteFilter.class);
+
+          // Our app-specific code
+          bind(Service.class).to(ServiceImpl.class);
+      }
+    });
+  }
+
+}
diff --git a/extensions/struts2/example/src/com/google/inject/struts2/example/Main.java b/extensions/struts2/example/src/com/google/inject/struts2/example/Main.java
new file mode 100644
index 0000000..eb4f0e2
--- /dev/null
+++ b/extensions/struts2/example/src/com/google/inject/struts2/example/Main.java
@@ -0,0 +1,42 @@
+/**
+ * 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 com.google.inject.struts2.example;
+
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.jetty.webapp.WebAppContext;
+
+/**
+ * Starts the example web server on port 8080. Run from "./struts2/example".
+ */
+public class Main {
+
+  public static void main(String[] args) throws Exception {
+    Server server = new Server();
+
+    Connector connector = new SelectChannelConnector();
+    connector.setPort(8080);
+    server.setConnectors(new Connector[] { connector });
+
+    WebAppContext webapp = new WebAppContext("./root", "/example");
+    server.addHandler(webapp);
+
+    server.start();
+    server.join();
+  }
+}
diff --git a/extensions/struts2/example/src/com/google/inject/struts2/example/Service.java b/extensions/struts2/example/src/com/google/inject/struts2/example/Service.java
new file mode 100644
index 0000000..419fd85
--- /dev/null
+++ b/extensions/struts2/example/src/com/google/inject/struts2/example/Service.java
@@ -0,0 +1,6 @@
+package com.google.inject.struts2.example;
+
+public interface Service {
+
+  String getStatus();
+}
diff --git a/extensions/struts2/example/src/com/google/inject/struts2/example/ServiceImpl.java b/extensions/struts2/example/src/com/google/inject/struts2/example/ServiceImpl.java
new file mode 100644
index 0000000..63b410f
--- /dev/null
+++ b/extensions/struts2/example/src/com/google/inject/struts2/example/ServiceImpl.java
@@ -0,0 +1,8 @@
+package com.google.inject.struts2.example;
+
+public class ServiceImpl implements Service {
+
+  public String getStatus() {
+    return "We're looking good.";
+  }
+}
diff --git a/extensions/struts2/example/src/struts.xml b/extensions/struts2/example/src/struts.xml
new file mode 100644
index 0000000..d48c95c
--- /dev/null
+++ b/extensions/struts2/example/src/struts.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE struts PUBLIC
+    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+    "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+<constant name="struts.devMode" value="true"></constant>
+  <!-- No need to specify a module here. See ExampleListener. -->
+
+  <!-- Register some actions, these get injected for you by Guice -->
+  <package name="default" extends="struts-default">
+    <action name="Count" 
+        class="com.google.inject.struts2.example.Count">
+      <result>/Counter.jsp</result>
+    </action>      
+  </package>
+
+</struts>
diff --git a/extensions/struts2/lib/ant-1.6.5.jar b/extensions/struts2/lib/ant-1.6.5.jar
new file mode 100644
index 0000000..3beb3b8
--- /dev/null
+++ b/extensions/struts2/lib/ant-1.6.5.jar
Binary files differ
diff --git a/extensions/struts2/lib/commons-fileupload-1.2.1.jar b/extensions/struts2/lib/commons-fileupload-1.2.1.jar
new file mode 100644
index 0000000..7db423e
--- /dev/null
+++ b/extensions/struts2/lib/commons-fileupload-1.2.1.jar
Binary files differ
diff --git a/extensions/struts2/lib/commons-io-1.3.2.jar b/extensions/struts2/lib/commons-io-1.3.2.jar
new file mode 100644
index 0000000..865c9e4
--- /dev/null
+++ b/extensions/struts2/lib/commons-io-1.3.2.jar
Binary files differ
diff --git a/extensions/struts2/lib/commons-logging-1.0.4.jar b/extensions/struts2/lib/commons-logging-1.0.4.jar
new file mode 100644
index 0000000..b73a80f
--- /dev/null
+++ b/extensions/struts2/lib/commons-logging-1.0.4.jar
Binary files differ
diff --git a/extensions/struts2/lib/core-3.1.1.jar b/extensions/struts2/lib/core-3.1.1.jar
new file mode 100644
index 0000000..ae0b635
--- /dev/null
+++ b/extensions/struts2/lib/core-3.1.1.jar
Binary files differ
diff --git a/extensions/struts2/lib/freemarker-2.3.16.jar b/extensions/struts2/lib/freemarker-2.3.16.jar
new file mode 100644
index 0000000..968c1d3
--- /dev/null
+++ b/extensions/struts2/lib/freemarker-2.3.16.jar
Binary files differ
diff --git a/extensions/struts2/lib/javassist.jar b/extensions/struts2/lib/javassist.jar
new file mode 100644
index 0000000..12c7b6c
--- /dev/null
+++ b/extensions/struts2/lib/javassist.jar
Binary files differ
diff --git a/extensions/struts2/lib/jetty-6.1.0.jar b/extensions/struts2/lib/jetty-6.1.0.jar
new file mode 100644
index 0000000..6b01acd
--- /dev/null
+++ b/extensions/struts2/lib/jetty-6.1.0.jar
Binary files differ
diff --git a/extensions/struts2/lib/jetty-util-6.1.0.jar b/extensions/struts2/lib/jetty-util-6.1.0.jar
new file mode 100644
index 0000000..b2afbc0
--- /dev/null
+++ b/extensions/struts2/lib/jetty-util-6.1.0.jar
Binary files differ
diff --git a/extensions/struts2/lib/jsp-2.1.jar b/extensions/struts2/lib/jsp-2.1.jar
new file mode 100644
index 0000000..c07d0f9
--- /dev/null
+++ b/extensions/struts2/lib/jsp-2.1.jar
Binary files differ
diff --git a/extensions/struts2/lib/jsp-api-2.1.jar b/extensions/struts2/lib/jsp-api-2.1.jar
new file mode 100644
index 0000000..3ecd2f5
--- /dev/null
+++ b/extensions/struts2/lib/jsp-api-2.1.jar
Binary files differ
diff --git a/extensions/struts2/lib/ognl-3.0.jar b/extensions/struts2/lib/ognl-3.0.jar
new file mode 100644
index 0000000..b64b5bb
--- /dev/null
+++ b/extensions/struts2/lib/ognl-3.0.jar
Binary files differ
diff --git a/extensions/struts2/lib/servlet-api-2.5.jar b/extensions/struts2/lib/servlet-api-2.5.jar
new file mode 100644
index 0000000..fb52493
--- /dev/null
+++ b/extensions/struts2/lib/servlet-api-2.5.jar
Binary files differ
diff --git a/extensions/struts2/lib/struts2-core-2.2.1.jar b/extensions/struts2/lib/struts2-core-2.2.1.jar
new file mode 100644
index 0000000..65b9c3f
--- /dev/null
+++ b/extensions/struts2/lib/struts2-core-2.2.1.jar
Binary files differ
diff --git a/extensions/struts2/lib/xwork-core-2.2.1.jar b/extensions/struts2/lib/xwork-core-2.2.1.jar
new file mode 100644
index 0000000..8fb2c81
--- /dev/null
+++ b/extensions/struts2/lib/xwork-core-2.2.1.jar
Binary files differ
diff --git a/extensions/struts2/pom.xml b/extensions/struts2/pom.xml
new file mode 100644
index 0000000..87e60d5
--- /dev/null
+++ b/extensions/struts2/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-struts2</artifactId>
+
+  <name>Google Guice - Extensions - Struts2</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.inject.extensions</groupId>
+      <artifactId>guice-servlet</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.5</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.struts</groupId>
+      <artifactId>struts2-core</artifactId>
+      <version>2.2.1</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/extensions/struts2/src/com/google/inject/struts2/GuiceObjectFactory.java b/extensions/struts2/src/com/google/inject/struts2/GuiceObjectFactory.java
new file mode 100644
index 0000000..4d7c485
--- /dev/null
+++ b/extensions/struts2/src/com/google/inject/struts2/GuiceObjectFactory.java
@@ -0,0 +1,247 @@
+/**
+ * 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 com.google.inject.struts2;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.internal.Annotations;
+import com.google.inject.servlet.ServletModule;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * @deprecated Use {@link com.google.inject.struts2.Struts2Factory} instead.
+ */
+@Deprecated
+public class GuiceObjectFactory extends ObjectFactory {
+
+  static final Logger logger =
+      Logger.getLogger(GuiceObjectFactory.class.getName());
+
+  Module module;
+  volatile Injector injector;
+  boolean developmentMode = false;
+  List<ProvidedInterceptor> interceptors
+      = new ArrayList<ProvidedInterceptor>();
+
+  @Override
+  public boolean isNoArgConstructorRequired() {
+    return false;
+  }
+
+  @Inject(value = "guice.module", required = false)
+  void setModule(String moduleClassName) {
+    try {
+      // Instantiate user's module.
+      @SuppressWarnings({"unchecked"})
+      Class<? extends Module> moduleClass =
+          (Class<? extends Module>) Class.forName(moduleClassName);
+      this.module = moduleClass.newInstance();
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Inject(value = "struts.devMode", required = false)
+  void setDevelopmentMode(String developmentMode) {
+    this.developmentMode = developmentMode.trim().equals("true");
+  }
+
+  Set<Class<?>> boundClasses = new HashSet<Class<?>>();
+
+  public Class getClassInstance(String name) throws ClassNotFoundException {
+    Class<?> clazz = super.getClassInstance(name);
+
+    synchronized (this) {
+      if (injector == null) {
+        // We can only bind each class once.
+        if (!boundClasses.contains(clazz)) {
+          try {
+            // Calling these methods now helps us detect ClassNotFoundErrors
+            // early.
+            clazz.getDeclaredFields();
+            clazz.getDeclaredMethods();
+
+            boundClasses.add(clazz);
+          } catch (Throwable t) {
+            // Struts should still work even though some classes aren't in the
+            // classpath. It appears we always get the exception here when
+            // this is the case.
+            return clazz;
+          }
+        }
+      }
+    }
+
+    return clazz;
+  }
+
+  @SuppressWarnings("unchecked")
+  public Object buildBean(Class clazz, Map extraContext) {
+    if (injector == null) {
+      synchronized (this) {
+        if (injector == null) {
+          createInjector();
+        }
+      }
+    }
+
+    return injector.getInstance(clazz);
+  }
+
+  private void createInjector() {
+    try {
+      logger.info("Creating injector...");
+      this.injector = Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          // Install default servlet bindings.
+          install(new ServletModule());
+
+          // Install user's module.
+          if (module != null) {
+            logger.info("Installing " + module + "...");
+            install(module);
+          }
+          else {
+            logger.info("No module found. Set 'guice.module' to a Module "
+                + "class name if you'd like to use one.");
+          }
+
+          // Tell the injector about all the action classes, etc., so it
+          // can validate them at startup.
+          for (Class<?> boundClass : boundClasses) {
+            // TODO: Set source from Struts XML.
+            bind(boundClass);
+          }
+
+          // Validate the interceptor class.
+          for (ProvidedInterceptor interceptor : interceptors) {
+            interceptor.validate(binder());
+          }
+        }
+      });
+
+      // Inject interceptors.
+      for (ProvidedInterceptor interceptor : interceptors) {
+        interceptor.inject();
+      }
+
+    } catch (Throwable t) {
+      t.printStackTrace();
+      System.exit(1);
+    }
+    logger.info("Injector created successfully.");
+  }
+
+  @SuppressWarnings("unchecked")
+  public Interceptor buildInterceptor(InterceptorConfig interceptorConfig,
+      Map interceptorRefParams) throws ConfigurationException {
+    // Ensure the interceptor class is present.
+    Class<? extends Interceptor> interceptorClass;
+    try {
+      interceptorClass = getClassInstance(interceptorConfig.getClassName());
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+
+    ProvidedInterceptor providedInterceptor = new ProvidedInterceptor(
+        interceptorConfig, interceptorRefParams, interceptorClass);
+    interceptors.add(providedInterceptor);
+    return providedInterceptor;
+  }
+
+  Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig,
+      Map interceptorRefParams) throws ConfigurationException {
+    return super.buildInterceptor(interceptorConfig, interceptorRefParams);
+  }
+
+  class ProvidedInterceptor implements Interceptor {
+
+    final InterceptorConfig config;
+    final Map params;
+    final Class<? extends Interceptor> interceptorClass;
+    Interceptor delegate;
+
+    ProvidedInterceptor(InterceptorConfig config, Map params,
+        Class<? extends Interceptor> interceptorClass) {
+      this.config = config;
+      this.params = params;
+      this.interceptorClass = interceptorClass;
+    }
+
+    void validate(Binder binder) {
+      // TODO: Set source from Struts XML.
+      if (hasScope(interceptorClass)) {
+        binder.addError("Scoping interceptors is not currently supported."
+            + " Please remove the scope annotation from "
+            + interceptorClass.getName() + ".");
+      }
+
+      // Make sure it implements Interceptor.
+      if (!Interceptor.class.isAssignableFrom(interceptorClass)) {
+        binder.addError(interceptorClass.getName() + " must implement "
+          + Interceptor.class.getName() + ".");
+      }
+    }
+
+    void inject() {
+      delegate = superBuildInterceptor(config, params);
+    }
+
+    public void destroy() {
+      if (null != delegate) {
+        delegate.destroy();
+      }
+    }
+
+    public void init() {
+      throw new AssertionError();
+    }
+
+    public String intercept(ActionInvocation invocation) throws Exception {
+      return delegate.intercept(invocation);
+    }
+  }
+
+  /**
+   * Returns true if the given class has a scope annotation.
+   */
+  private static boolean hasScope(Class<? extends Interceptor> interceptorClass) {
+    for (Annotation annotation : interceptorClass.getAnnotations()) {
+      if (Annotations.isScopeAnnotation(annotation.annotationType())) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java b/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java
new file mode 100644
index 0000000..6e9263a
--- /dev/null
+++ b/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java
@@ -0,0 +1,231 @@
+/**
+ * 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 com.google.inject.struts2;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Injector;
+import com.google.inject.internal.Annotations;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Cleanup up version from Bob's GuiceObjectFactory. Now works properly with
+ * GS2 and fixes several bugs.
+ *
+ * @author dhanji@gmail.com
+ * @author benmccann.com
+ */
+public class Struts2Factory extends ObjectFactory {
+
+  private static final long serialVersionUID = 1L;
+  private static final Logger logger = Logger.getLogger(Struts2Factory.class.getName());
+  private static final String ERROR_NO_INJECTOR =
+      "Cannot find a Guice injector.  Are you sure you registered a GuiceServletContextListener "
+    + "that uses the Struts2GuicePluginModule in your application's web.xml?";
+
+  private static @com.google.inject.Inject Injector injector;
+
+  private final List<ProvidedInterceptor> interceptors = new ArrayList<ProvidedInterceptor>();
+  private volatile Injector strutsInjector;
+
+  @Override
+  public boolean isNoArgConstructorRequired() {
+    return false;
+  }
+
+  @Inject(value = "guice.module", required = false)
+  void setModule(String moduleClassName) {
+    throw new RuntimeException("The struts2 plugin no longer supports"
+        + " specifying a module via the 'guice.module' property in XML."
+        + " Please install your module via a GuiceServletContextListener instead.");
+  }
+
+  Set<Class<?>> boundClasses = new HashSet<Class<?>>();
+
+  public Class<?> getClassInstance(String name) throws ClassNotFoundException {
+    Class<?> clazz = super.getClassInstance(name);
+
+    synchronized (this) {
+      if (strutsInjector == null) {
+        // We can only bind each class once.
+        if (!boundClasses.contains(clazz)) {
+          try {
+            // Calling these methods now helps us detect ClassNotFoundErrors
+            // early.
+            clazz.getDeclaredFields();
+            clazz.getDeclaredMethods();
+
+            boundClasses.add(clazz);
+          } catch (Throwable t) {
+            // Struts should still work even though some classes aren't in the
+            // classpath. It appears we always get the exception here when
+            // this is the case.
+            return clazz;
+          }
+        }
+      }
+    }
+
+    return clazz;
+  }
+
+  @Override @SuppressWarnings("unchecked")
+  public Object buildBean(Class clazz, Map<String, Object> extraContext) {
+    if (strutsInjector == null) {
+      synchronized (this) {
+        if (strutsInjector == null) {
+          createInjector();
+        }
+      }
+    }
+    return strutsInjector.getInstance(clazz);
+  }
+
+  private void createInjector() {
+    logger.info("Loading struts2 Guice support...");
+
+    // Something is wrong, since this should be there if GuiceServletContextListener
+    // was present.
+    if (injector == null) {
+      logger.severe(ERROR_NO_INJECTOR);
+      throw new RuntimeException(ERROR_NO_INJECTOR);
+    }
+
+    this.strutsInjector = injector.createChildInjector(new AbstractModule() {
+      protected void configure() {
+
+        // Tell the injector about all the action classes, etc., so it
+        // can validate them at startup.
+        for (Class<?> boundClass : boundClasses) {
+          // TODO: Set source from Struts XML.
+          bind(boundClass);
+        }
+
+        // Validate the interceptor class.
+        for (ProvidedInterceptor interceptor : interceptors) {
+          interceptor.validate(binder());
+        }
+      }
+    });
+
+    // Inject interceptors.
+    for (ProvidedInterceptor interceptor : interceptors) {
+      interceptor.inject();
+    }
+
+    logger.info("Injector created successfully.");
+  }
+
+  @SuppressWarnings("unchecked")
+  public Interceptor buildInterceptor(InterceptorConfig interceptorConfig,
+      Map interceptorRefParams) throws ConfigurationException {
+    // Ensure the interceptor class is present.
+    Class<? extends Interceptor> interceptorClass;
+    try {
+      interceptorClass = (Class<? extends Interceptor>)
+          getClassInstance(interceptorConfig.getClassName());
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+
+    ProvidedInterceptor providedInterceptor = new ProvidedInterceptor(
+        interceptorConfig, interceptorRefParams, interceptorClass);
+    interceptors.add(providedInterceptor);
+    return providedInterceptor;
+  }
+
+  private Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig,
+      Map<String, String> interceptorRefParams) throws ConfigurationException {
+    return super.buildInterceptor(interceptorConfig, interceptorRefParams);
+  }
+
+  private class ProvidedInterceptor implements Interceptor {
+
+    private static final long serialVersionUID = 1L;
+
+    private final InterceptorConfig config;
+    private final Map<String, String> params;
+    private final Class<? extends Interceptor> interceptorClass;
+    private Interceptor delegate;
+
+    ProvidedInterceptor(InterceptorConfig config, Map<String, String> params,
+        Class<? extends Interceptor> interceptorClass) {
+      this.config = config;
+      this.params = params;
+      this.interceptorClass = interceptorClass;
+    }
+
+    void validate(Binder binder) {
+      // TODO: Set source from Struts XML.
+      if (hasScope(interceptorClass)) {
+        binder.addError("Scoping interceptors is not currently supported."
+            + " Please remove the scope annotation from "
+            + interceptorClass.getName() + ".");
+      }
+
+      // Make sure it implements Interceptor.
+      if (!Interceptor.class.isAssignableFrom(interceptorClass)) {
+        binder.addError(interceptorClass.getName() + " must implement "
+          + Interceptor.class.getName() + ".");
+      }
+    }
+
+    void inject() {
+      delegate = superBuildInterceptor(config, params);
+    }
+
+    public void destroy() {
+      if (null != delegate) {
+        delegate.destroy();
+      }
+    }
+
+    public void init() {
+      throw new AssertionError();
+    }
+
+    public String intercept(ActionInvocation invocation) throws Exception {
+      return delegate.intercept(invocation);
+    }
+  }
+
+  /**
+   * Returns true if the given class has a scope annotation.
+   */
+  private static boolean hasScope(Class<? extends Interceptor> interceptorClass) {
+    for (Annotation annotation : interceptorClass.getAnnotations()) {
+      if (Annotations.isScopeAnnotation(annotation.annotationType())) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/extensions/struts2/src/com/google/inject/struts2/Struts2GuicePluginModule.java b/extensions/struts2/src/com/google/inject/struts2/Struts2GuicePluginModule.java
new file mode 100644
index 0000000..a20ee53
--- /dev/null
+++ b/extensions/struts2/src/com/google/inject/struts2/Struts2GuicePluginModule.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2010 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.inject.struts2;
+
+import com.google.inject.AbstractModule;
+
+/**
+ * Initializes the Struts 2 Guice Plugin. Must be added to the injector returned
+ * by {@link com.google.inject.servlet.GuiceServletContextListener#getInjector}.
+ *
+ * @author benmccann.com
+ */
+public class Struts2GuicePluginModule extends AbstractModule {
+
+  @Override
+  protected void configure() {
+    requestStaticInjection(Struts2Factory.class);
+  }
+
+}
diff --git a/extensions/struts2/src/struts-plugin.xml b/extensions/struts2/src/struts-plugin.xml
new file mode 100644
index 0000000..40bf990
--- /dev/null
+++ b/extensions/struts2/src/struts-plugin.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE struts PUBLIC
+  "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+  "http://struts.apache.org/dtds/struts-2.0.dtd">
+    
+<struts>
+
+  <bean type="com.opensymphony.xwork2.ObjectFactory" 
+        name="guice"
+        class="com.google.inject.struts2.Struts2Factory"/>
+
+  <!--  Make the Guice object factory the automatic default -->
+  <constant name="struts.objectFactory" value="guice" />
+
+</struts>
diff --git a/extensions/struts2/test/com/google/inject/struts2/Struts2FactoryTest.java b/extensions/struts2/test/com/google/inject/struts2/Struts2FactoryTest.java
new file mode 100644
index 0000000..3beca7f
--- /dev/null
+++ b/extensions/struts2/test/com/google/inject/struts2/Struts2FactoryTest.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2010 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.inject.struts2;
+
+import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+
+import junit.framework.TestCase;
+
+import java.util.Date;
+
+/**
+ * Test for Struts2Factory
+ *
+ * @author benmccann.com
+ */
+public class Struts2FactoryTest extends TestCase {
+
+  private static final Date TODAY = new Date();
+
+  public static class TestListener extends GuiceServletContextListener {
+
+    private final Module module;
+
+    public TestListener(Module module) {
+      this.module = module;
+    }
+
+    @Override
+    protected Injector getInjector() {
+      return Guice.createInjector(
+          new Struts2GuicePluginModule(),
+          new ServletModule() {
+            @Override
+            protected void configureServlets() {
+              // Struts 2 setup
+              bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class);
+              filter("/*").through(StrutsPrepareAndExecuteFilter.class);
+            }
+          },
+          module
+      );
+    }
+
+  }
+
+  public void testStruts2Factory() {
+    Struts2Factory s2Factory = new Struts2Factory();
+    TestListener testListener = new TestListener(new AbstractModule() {
+      @Override
+      protected void configure() {
+      }
+
+      @Provides @SuppressWarnings("unused")
+      Date provideDate() {
+        return TODAY;
+      }
+    });
+    assertEquals(TODAY, testListener.getInjector().getInstance(Date.class));
+    assertEquals(TODAY, s2Factory.buildBean(Date.class, null));
+  }
+
+}
diff --git a/extensions/testlib/build.properties b/extensions/testlib/build.properties
new file mode 100644
index 0000000..436a2f4
--- /dev/null
+++ b/extensions/testlib/build.properties
@@ -0,0 +1,7 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.testing.fieldbinder.FieldBindingModuleTest
+module=com.google.inject.testing
+fragment=true
diff --git a/extensions/testlib/build.xml b/extensions/testlib/build.xml
new file mode 100644
index 0000000..b85d6ec
--- /dev/null
+++ b/extensions/testlib/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-testlib" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/testlib/pom.xml b/extensions/testlib/pom.xml
new file mode 100644
index 0000000..49c45b4
--- /dev/null
+++ b/extensions/testlib/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-testlib</artifactId>
+
+  <name>Google Guice - Extensions - TestLib</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>**/TestScope*</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java b/extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java
new file mode 100644
index 0000000..6c75fc7
--- /dev/null
+++ b/extensions/testlib/src/com/google/inject/testing/fieldbinder/Bind.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 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.inject.testing.fieldbinder;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used by {@link BoundFieldModule} to indicate that a field should be bound to its
+ * value using Guice.
+ *
+ * @see BoundFieldModule
+ * @author eatnumber1@google.com (Russ Harmon)
+ */
+@Retention(RUNTIME)
+@Target({FIELD})
+public @interface Bind {
+  /**
+   * If specified, {@link BoundFieldModule} will bind the annotated field's value to this type,
+   * rather than to the field's actual type.
+   */
+  Class<?> to() default Bind.class;
+
+  /**
+   * If true, {@link BoundFieldModule} will delay retrieving the field's value until injection time
+   * rather than eagerly fetching it at configure time.
+   * 
+   * <p>This option is not supported with Provider valued fields.
+   */
+  boolean lazy() default false;
+}
diff --git a/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java b/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java
new file mode 100644
index 0000000..c280848
--- /dev/null
+++ b/extensions/testlib/src/com/google/inject/testing/fieldbinder/BoundFieldModule.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2014 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.inject.testing.fieldbinder;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.inject.Binder;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.internal.Annotations;
+import com.google.inject.spi.Message;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * Automatically creates Guice bindings for fields in an object annotated with {@link Bind}.
+ *
+ * <p>This module is intended for use in tests to reduce the code needed to bind local fields
+ * (usually mocks) for injection.
+ *
+ * <p>The following rules are followed in determining how fields are bound using this module:
+ *
+ * <ul>
+ * <li>
+ * For each {@link Bind} annotated field of an object and its superclasses, this module will bind
+ * that field's type to that field's value at injector creation time. This includes both instance
+ * and static fields.
+ * </li>
+ * <li>
+ * If {@link Bind#to} is specified, the field's value will be bound to the class specified by
+ * {@link Bind#to} instead of the field's actual type.
+ * </li>
+ * <li>
+ * If a {@link BindingAnnotation} or {@link javax.inject.Qualifier} is present on the field,
+ * that field will be bound using that annotation via {@link AnnotatedBindingBuilder#annotatedWith}.
+ * For example, {@code bind(Foo.class).annotatedWith(BarAnnotation.class).toInstance(theValue)}.
+ * It is an error to supply more than one {@link BindingAnnotation} or
+ * {@link javax.inject.Qualifier}.
+ * </li>
+ * <li>
+ * If the field is of type {@link Provider}, the field's value will be bound as a {@link Provider}
+ * using {@link LinkedBindingBuilder#toProvider} to the provider's parameterized type. For example,
+ * {@code Provider<Integer>} binds to {@link Integer}. Attempting to bind a non-parameterized
+ * {@link Provider} without a {@link Bind#to} clause is an error.
+ * </li>
+ * </ul>
+ *
+ * <p>Example use:
+ * <pre><code>
+ * public class TestFoo {
+ *   // bind(new TypeLiteral{@code <List<Object>>}() {}).toInstance(listOfObjects);
+ *   {@literal @}Bind private List{@code <Object>} listOfObjects = Lists.of();
+ *   
+ *   // bind(String.class).toProvider(new Provider() { public String get() { return userName; }});
+ *   {@literal @}Bind(lazy = true) private String userName;
+ *
+ *   // bind(SuperClass.class).toInstance(aSubClass);
+ *   {@literal @}Bind(to = SuperClass.class) private SubClass aSubClass = new SubClass();
+ *
+ *   // bind(Object.class).annotatedWith(MyBindingAnnotation.class).toInstance(object2);
+ *   {@literal @}Bind
+ *   {@literal @}MyBindingAnnotation
+ *   private String myString = "hello";
+ *
+ *   // bind(Object.class).toProvider(myProvider);
+ *   {@literal @}Bind private Provider{@code <Object>} myProvider = getProvider();
+ *
+ *   {@literal @}Before public void setUp() {
+ *     Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
+ *   }
+ * }
+ * </code></pre>
+ *
+ * @see Bind
+ * @author eatnumber1@google.com (Russ Harmon)
+ */
+public final class BoundFieldModule implements Module {
+  private final Object instance;
+
+  // Note that binder is not initialized until configure() is called.
+  private Binder binder;
+
+  private BoundFieldModule(Object instance) {
+    this.instance = instance;
+  }
+
+  /**
+   * Create a BoundFieldModule which binds the {@link Bind} annotated fields of {@code instance}.
+   *
+   * @param instance the instance whose fields will be bound.
+   * @return a module which will bind the {@link Bind} annotated fields of {@code instance}.
+   */
+  public static BoundFieldModule of(Object instance) {
+    return new BoundFieldModule(instance);
+  }
+
+  private static class BoundFieldException extends RuntimeException {
+    private final Message message;
+
+    BoundFieldException(Message message) {
+      super(message.getMessage());
+      this.message = message;
+    }
+  }
+
+  private class BoundFieldInfo {
+    /** The field itself. */
+    final Field field;
+
+    /**
+     * The actual type of the field.
+     *
+     * <p>For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be
+     * {@link Number}.
+     */
+    final TypeLiteral<?> type;
+
+    /** The {@link Bind} annotation which is present on the field. */
+    final Bind bindAnnotation;
+
+    /**
+     * The type this field will bind to.
+     *
+     * <p>For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be
+     * {@link Object} and {@code @Bind Number one = new Integer(1);} will be {@link Number}.
+     */
+    final TypeLiteral<?> boundType;
+
+    /**
+     * The "natural" type of this field.
+     *
+     * <p>For example, {@code @Bind(to = Object.class) Number one = new Integer(1);} will be
+     * {@link Number}, and {@code @Bind(to = Object.class) Provider<Number> one = new Integer(1);}
+     * will be {@link Number}.
+     *
+     * @see #getNaturalFieldType
+     */
+    final Optional<TypeLiteral<?>> naturalType;
+
+    BoundFieldInfo(
+        Field field,
+        Bind bindAnnotation,
+        TypeLiteral<?> fieldType) {
+      this.field = field;
+      this.type = fieldType;
+      this.bindAnnotation = bindAnnotation;
+
+      field.setAccessible(true);
+
+      this.naturalType = getNaturalFieldType();
+      this.boundType = getBoundType();
+    }
+
+    private TypeLiteral<?> getBoundType() {
+      Class<?> bindClass = bindAnnotation.to();
+      // Bind#to's default value is Bind.class which is used to represent that no explicit binding
+      // type is requested.
+      if (bindClass == Bind.class) {
+        Preconditions.checkState(naturalType != null);
+        if (!this.naturalType.isPresent()) {
+          throwBoundFieldException(
+              field,
+              "Non parameterized Provider fields must have an explicit "
+              + "binding class via @Bind(to = Foo.class)");
+        }
+        return this.naturalType.get();
+      } else {
+        return TypeLiteral.get(bindClass);
+      }
+    }
+
+    /**
+     * Retrieves the type this field binds to naturally.
+     *
+     * <p>A field's "natural" type specifically ignores the to() method on the @Bind annotation, is
+     * the parameterized type if the field's actual type is a parameterized {@link Provider}, is
+     * {@link Optional#absent()} if this field is a non-parameterized {@link Provider} and otherwise
+     * is the field's actual type.
+     *
+     * @return the type this field binds to naturally, or {@link Optional#absent()} if this field is
+     * a non-parameterized {@link Provider}.
+     */
+    private Optional<TypeLiteral<?>> getNaturalFieldType() {
+      if (isTransparentProvider(type.getRawType())) {
+        Type providerType = type.getType();
+        if (providerType instanceof Class) {
+          return Optional.absent();
+        }
+        Preconditions.checkState(providerType instanceof ParameterizedType);
+        Type[] providerTypeArguments = ((ParameterizedType) providerType).getActualTypeArguments();
+        Preconditions.checkState(providerTypeArguments.length == 1);
+        return Optional.<TypeLiteral<?>>of(TypeLiteral.get(providerTypeArguments[0]));
+      } else {
+        return Optional.<TypeLiteral<?>>of(type);
+      }
+    }
+
+    Object getValue() {
+      try {
+        return field.get(instance);
+      } catch (IllegalAccessException e) {
+        // Since we called setAccessible(true) on this field in the constructor, this is a
+        // programming error if it occurs.
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  private static boolean hasInject(Field field) {
+    return field.isAnnotationPresent(javax.inject.Inject.class)
+        || field.isAnnotationPresent(com.google.inject.Inject.class);
+  }
+
+  /**
+   * Retrieve a {@link BoundFieldInfo}.
+   *
+   * <p>This returns a {@link BoundFieldInfo} if the field has a {@link Bind} annotation.
+   * Otherwise it returns {@link Optional#absent()}.
+   */
+  private Optional<BoundFieldInfo> getBoundFieldInfo(
+      TypeLiteral<?> containingClassType,
+      Field field) {
+    Bind bindAnnotation = field.getAnnotation(Bind.class);
+    if (bindAnnotation == null) {
+      return Optional.absent();
+    }
+    if (hasInject(field)) {
+      throwBoundFieldException(
+          field,
+          "Fields annotated with both @Bind and @Inject are illegal.");
+    }
+    return Optional.of(
+        new BoundFieldInfo(
+            field,
+            bindAnnotation,
+            containingClassType.getFieldType(field)));
+  }
+
+  private LinkedBindingBuilder<?> verifyBindingAnnotations(
+      Field field,
+      AnnotatedBindingBuilder<?> annotatedBinder) {
+    LinkedBindingBuilder<?> binderRet = annotatedBinder;
+    for (Annotation annotation : field.getAnnotations()) {
+      Class<? extends Annotation> annotationType = annotation.annotationType();
+      if (Annotations.isBindingAnnotation(annotationType)) {
+        // not returning here ensures that annotatedWith will be called multiple times if this field
+        // has multiple BindingAnnotations, relying on the binder to throw an error in this case.
+        binderRet = annotatedBinder.annotatedWith(annotation);
+      }
+    }
+    return binderRet;
+  }
+
+  /**
+   * Determines if {@code clazz} is a "transparent provider".
+   *
+   * <p>A transparent provider is a {@link com.google.inject.Provider} or
+   * {@link javax.inject.Provider} which binds to it's parameterized type when used as the argument
+   * to {@link Binder#bind}.
+   *
+   * <p>A {@link Provider} is transparent if the base class of that object is {@link Provider}. In
+   * other words, subclasses of {@link Provider} are not transparent. As a special case, if a
+   * {@link Provider} has no parameterized type but is otherwise transparent, then it is considered
+   * transparent.
+   */
+  private static boolean isTransparentProvider(Class<?> clazz) {
+    return com.google.inject.Provider.class == clazz || javax.inject.Provider.class == clazz;
+  }
+
+  private void bindField(final BoundFieldInfo fieldInfo) {
+    if (fieldInfo.naturalType.isPresent()) {
+      Class<?> naturalRawType = fieldInfo.naturalType.get().getRawType();
+      Class<?> boundRawType = fieldInfo.boundType.getRawType();
+      if (!boundRawType.isAssignableFrom(naturalRawType)) {
+        throwBoundFieldException(
+            fieldInfo.field,
+            "Requested binding type \"%s\" is not assignable from field binding type \"%s\"",
+            boundRawType.getName(),
+            naturalRawType.getName());
+      }
+    }
+
+    AnnotatedBindingBuilder<?> annotatedBinder = binder.bind(fieldInfo.boundType);
+    LinkedBindingBuilder<?> binder = verifyBindingAnnotations(fieldInfo.field, annotatedBinder);
+
+    // It's unfortunate that Field.get() just returns Object rather than the actual type (although
+    // that would be impossible) because as a result calling binder.toInstance or binder.toProvider
+    // is impossible to do without an unchecked cast. This is safe if fieldInfo.naturalType is
+    // present because compatibility is checked explicitly above, but is _unsafe_ if
+    // fieldInfo.naturalType is absent which occurrs when a non-parameterized Provider is used with
+    // @Bind(to = ...)
+    @SuppressWarnings("unchecked")
+    AnnotatedBindingBuilder<Object> binderUnsafe = (AnnotatedBindingBuilder<Object>) binder;
+
+    if (isTransparentProvider(fieldInfo.type.getRawType())) {
+      if (fieldInfo.bindAnnotation.lazy()) {
+        // We don't support this because it is confusing about when values are captured.
+        throwBoundFieldException(fieldInfo.field, 
+            "'lazy' is incompatible with Provider valued fields");
+      }
+      // This is safe because we checked that the field's type is Provider above.
+      @SuppressWarnings("unchecked")
+      Provider<?> fieldValueUnsafe = (Provider<?>) getFieldValue(fieldInfo);
+      binderUnsafe.toProvider(fieldValueUnsafe);
+    } else if (fieldInfo.bindAnnotation.lazy()) {
+      binderUnsafe.toProvider(new Provider<Object>() {
+        @Override public Object get() {
+          return getFieldValue(fieldInfo);
+        }
+      });
+    } else {
+      binderUnsafe.toInstance(getFieldValue(fieldInfo));
+    }
+  }
+
+  private Object getFieldValue(final BoundFieldInfo fieldInfo) {
+    Object fieldValue = fieldInfo.getValue();
+    if (fieldValue == null) {
+      throwBoundFieldException(
+          fieldInfo.field,
+          "Binding to null values is not allowed. "
+              + "Use Providers.of(null) if this is your intended behavior.",
+              fieldInfo.field.getName());
+    }
+    return fieldValue;
+  }
+
+  private void throwBoundFieldException(Field field, String format, Object... args) {
+    Preconditions.checkNotNull(binder);
+    String source = String.format(
+        "%s field %s",
+        field.getDeclaringClass().getName(),
+        field.getName());
+    throw new BoundFieldException(new Message(source, String.format(format, args)));
+  }
+
+  @Override
+  public void configure(Binder binder) {
+    binder = binder.skipSources(BoundFieldModule.class);
+    this.binder = binder;
+
+    TypeLiteral<?> currentClassType = TypeLiteral.get(instance.getClass());
+    while (currentClassType.getRawType() != Object.class) {
+      for (Field field : currentClassType.getRawType().getDeclaredFields()) {
+        try {
+          Optional<BoundFieldInfo> fieldInfoOpt =
+              getBoundFieldInfo(currentClassType, field);
+          if (fieldInfoOpt.isPresent()) {
+            bindField(fieldInfoOpt.get());
+          }
+        } catch (BoundFieldException e) {
+          // keep going to try to collect as many errors as possible
+          binder.addError(e.message);
+        }
+      }
+      currentClassType =
+          currentClassType.getSupertype(currentClassType.getRawType().getSuperclass());
+    }
+  }
+}
diff --git a/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java b/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java
new file mode 100644
index 0000000..2db1215
--- /dev/null
+++ b/extensions/testlib/test/com/google/inject/testing/fieldbinder/BoundFieldModuleTest.java
@@ -0,0 +1,732 @@
+/*
+ * Copyright (C) 2014 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.inject.testing.fieldbinder;
+
+import static com.google.inject.Asserts.assertContains;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+import com.google.inject.ConfigurationException;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.inject.Qualifier;
+
+/** Unit tests for {@link BoundFieldModule}. */
+public class BoundFieldModuleTest extends TestCase {
+  public void testBindingNothing() {
+    Object instance = new Object() {};
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Guice.createInjector(module);
+
+    // If we didn't throw an exception, we succeeded.
+  }
+
+  public void testBindingOnePrivate() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind private Integer anInt = testValue;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Integer.class));
+  }
+
+  public void testBindingOnePublic() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind public Integer anInt = testValue;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Integer.class));
+  }
+
+  private static class FieldBindableClass {
+    @Bind Integer anInt;
+
+    FieldBindableClass(Integer anInt) {
+      this.anInt = anInt;
+    }
+  }
+
+  private static class FieldBindableSubclass extends FieldBindableClass {
+    FieldBindableSubclass(Integer anInt) {
+      super(anInt);
+    }
+  }
+
+  public void testSuperTypeBinding() {
+    FieldBindableSubclass instance = new FieldBindableSubclass(1024);
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(instance.anInt, injector.getInstance(Integer.class));
+  }
+
+  public void testBindingTwo() {
+    final Integer testValue = 1024;
+    final String testString = "Hello World!";
+    Object instance = new Object() {
+      @Bind private Integer anInt = testValue;
+      @Bind private String aString = testString;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Integer.class));
+    assertEquals(testString, injector.getInstance(String.class));
+  }
+
+  public void testBindingSuperType() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind(to = Number.class) private Integer anInt = testValue;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Number.class));
+  }
+
+  public void testBindingSuperTypeAccessSubType() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind(to = Number.class) private Integer anInt = testValue;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    try {
+      injector.getInstance(Integer.class);
+    } catch (ConfigurationException e) {
+      assertContains(
+          e.getMessage(),
+          "Could not find a suitable constructor in java.lang.Integer");
+    }
+  }
+
+  public void testBindingIncorrectTypeProviderFails() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind(to = String.class) private Provider<Integer> anIntProvider = new Provider<Integer>() {
+        @Override public Integer get() {
+          return testValue;
+        }
+      };
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException e) {
+      assertContains(
+          e.getMessage(),
+          "Requested binding type \"java.lang.String\" is not "
+          + "assignable from field binding type \"java.lang.Integer\"");
+    }
+  }
+
+  @BindingAnnotation
+  @Retention(RUNTIME)
+  private static @interface SomeBindingAnnotation {}
+
+  public void testBindingWithBindingAnnotation() {
+    final Integer testValue1 = 1024, testValue2 = 2048;
+    Object instance = new Object() {
+      @Bind private Integer anInt = testValue1;
+
+      @Bind
+      @SomeBindingAnnotation
+      private Integer anotherInt = testValue2;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue1, injector.getInstance(Integer.class));
+    assertEquals(
+        testValue2,
+        injector.getInstance(Key.get(Integer.class, SomeBindingAnnotation.class)));
+  }
+
+  @Qualifier
+  @Retention(RUNTIME)
+  private static @interface SomeQualifier {}
+
+  public void testBindingWithQualifier() {
+    final Integer testValue1 = 1024, testValue2 = 2048;
+    Object instance = new Object() {
+      @Bind private Integer anInt = testValue1;
+
+      @Bind
+      @SomeQualifier
+      private Integer anotherInt = testValue2;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue1, injector.getInstance(Integer.class));
+    assertEquals(
+        testValue2,
+        injector.getInstance(Key.get(Integer.class, SomeQualifier.class)));
+  }
+
+  public void testCanReuseBindingAnnotationsWithDifferentValues() {
+    final Integer testValue1 = 1024, testValue2 = 2048;
+    final String name1 = "foo", name2 = "bar";
+    Object instance = new Object() {
+      @Bind
+      @Named(name1)
+      private Integer anInt = testValue1;
+
+      @Bind
+      @Named(name2)
+      private Integer anotherInt = testValue2;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(
+        testValue1,
+        injector.getInstance(Key.get(Integer.class, Names.named(name1))));
+    assertEquals(
+        testValue2,
+        injector.getInstance(Key.get(Integer.class, Names.named(name2))));
+  }
+
+  public void testBindingWithValuedBindingAnnotation() {
+    final Integer testValue1 = 1024, testValue2 = 2048;
+    final String name = "foo";
+    Object instance = new Object() {
+      @Bind private Integer anInt = testValue1;
+
+      @Bind
+      @Named(name)
+      private Integer anotherInt = testValue2;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue1, injector.getInstance(Integer.class));
+    assertEquals(
+        testValue2,
+        injector.getInstance(Key.get(Integer.class, Names.named(name))));
+  }
+
+  public void testBindingWithGenerics() {
+    final List<Integer> testIntList = Arrays.asList(new Integer[] {1, 2, 3});
+    final List<Boolean> testBoolList = Arrays.asList(new Boolean[] {true, true, false});
+    Object instance = new Object() {
+      @Bind private List<Integer> anIntList = testIntList;
+      @Bind private List<Boolean> aBoolList = testBoolList;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testIntList, injector.getInstance(new Key<List<Integer>>() {}));
+    assertEquals(testBoolList, injector.getInstance(new Key<List<Boolean>>() {}));
+  }
+
+  public void testBoundValueDoesntChange() {
+    Integer testValue = 1024;
+    FieldBindableClass instance = new FieldBindableClass(testValue);
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Integer.class));
+    instance.anInt++;
+    assertEquals(testValue, injector.getInstance(Integer.class));
+  }
+
+  public void testIncompatibleBindingType() {
+    final Integer testInt = 1024;
+    Object instance = new Object() {
+      @Bind(to = String.class) private Integer anInt = testInt;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Requested binding type \"java.lang.String\" is not assignable from field binding type "
+          + "\"java.lang.Integer\"");
+    }
+  }
+
+  public void testFailureOnMultipleBindingAnnotations() {
+    final Integer testInt = 1024;
+    Object instance = new Object() {
+      @Bind
+      @Named("a")
+      @SomeBindingAnnotation
+      private Integer anInt = testInt;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+    } catch (CreationException e) {
+      assertContains(e.getMessage(), "More than one annotation is specified for this binding.");
+    }
+  }
+
+  public void testBindingSuperTypeAndBindingAnnotation() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind(to = Number.class)
+      @Named("foo")
+      private Integer anInt = testValue;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Key.get(Number.class, Names.named("foo"))));
+  }
+
+  public void testBindingProvider() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind private Provider<Integer> anInt = new Provider<Integer>() {
+        @Override public Integer get() {
+          return testValue;
+        }
+      };
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Integer.class));
+  }
+
+  public void testBindingNullField() {
+    Object instance = new Object() {
+      @Bind private Integer anInt = null;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Binding to null values is not allowed. "
+          + "Use Providers.of(null) if this is your intended behavior.");
+    }
+  }
+
+  public void testBindingNullProvider() {
+    Object instance = new Object() {
+      @Bind private Provider<Integer> anIntProvider = null;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Binding to null values is not allowed. "
+          + "Use Providers.of(null) if this is your intended behavior.");
+    }
+  }
+
+  private static class IntegerProvider implements Provider<Integer> {
+    private final Integer value;
+
+    IntegerProvider(Integer value) {
+      this.value = value;
+    }
+
+    @Override public Integer get() {
+      return value;
+    }
+  }
+
+  public void testProviderSubclassesBindToTheProviderItself() {
+    final IntegerProvider integerProvider = new IntegerProvider(1024);
+    Object instance = new Object() {
+      @Bind private IntegerProvider anIntProvider = integerProvider;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(integerProvider, injector.getInstance(IntegerProvider.class));
+  }
+
+  public void testProviderSubclassesDoNotBindParameterizedType() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind private IntegerProvider anIntProvider = new IntegerProvider(testValue);
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    try {
+      injector.getInstance(Integer.class);
+      fail();
+    } catch (ConfigurationException e) {
+      assertContains(e.getMessage(), "Could not find a suitable constructor in java.lang.Integer.");
+    }
+  }
+
+  private static class ParameterizedObject<T> {
+    ParameterizedObject(T instance) {
+      this.instance = instance;
+    }
+
+    @Bind private T instance;
+  }
+
+  public void testBindParameterizedTypeFails() {
+    ParameterizedObject<Integer> instance = new ParameterizedObject<Integer>(0);
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(), "T cannot be used as a key; It is not fully specified.");
+    }
+  }
+
+  public void testBindSubclassOfParameterizedTypeSucceeds() {
+    final Integer testValue = 1024;
+    ParameterizedObject<Integer> instance = new ParameterizedObject<Integer>(testValue) {};
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Integer.class));
+  }
+
+  public void testBindArray() {
+    final Integer[] testArray = new Integer[] { 1024, 2048 };
+    Object instance = new Object() {
+      @Bind private Integer[] anIntArray = testArray;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testArray, injector.getInstance(Integer[].class));
+  }
+
+  public void testRawProviderCannotBeBound() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind private Provider anIntProvider = new Provider() {
+        @Override public Object get() {
+          return testValue;
+        }
+      };
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(),
+          "Non parameterized Provider fields must have an "
+          + "explicit binding class via @Bind(to = Foo.class)");
+    }
+  }
+
+  public void testExplicitlyBoundRawProviderCanBeBound() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind(to = Integer.class) private Provider anIntProvider = new Provider() {
+        @Override public Object get() {
+          return testValue;
+        }
+      };
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Integer.class));
+  }
+
+  public void testRawProviderCanBindToIncorrectType() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind(to = String.class) private Provider anIntProvider = new Provider() {
+        @Override public Object get() {
+          return testValue;
+        }
+      };
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(String.class));
+  }
+
+  public void testMultipleErrorsAreAggregated() {
+    Object instance = new Object() {
+      @Bind private Provider aProvider;
+      @Bind(to = String.class) private Integer anInt;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    try {
+      Guice.createInjector(module);
+    } catch (CreationException e) {
+      assertEquals(2, e.getErrorMessages().size());
+    }
+  }
+
+  public void testBindingProviderWithProviderSubclassValue() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind private Provider<Integer> anIntProvider = new IntegerProvider(testValue);
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Integer.class));
+  }
+
+  public void testBoundFieldsCannotBeInjected() {
+    Object instance = new Object() {
+      @Bind
+      @Inject
+      Integer anInt = 0;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+    } catch (CreationException e) {
+      assertContains(
+          e.getMessage(),
+          "Fields annotated with both @Bind and @Inject are illegal.");
+    }
+  }
+
+  public void testIncrementingProvider() {
+    final Integer testBaseValue = 1024;
+    Object instance = new Object() {
+      @Bind private Provider<Integer> anIntProvider = new Provider<Integer>() {
+        private int value = testBaseValue;
+
+        @Override public Integer get() {
+          return value++;
+        }
+      };
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testBaseValue, injector.getInstance(Integer.class));
+    assertEquals((Integer) (testBaseValue + 1), injector.getInstance(Integer.class));
+    assertEquals((Integer) (testBaseValue + 2), injector.getInstance(Integer.class));
+  }
+
+  public void testProviderDoesNotProvideDuringInjectorConstruction() {
+    Object instance = new Object() {
+      @Bind private Provider<Integer> myIntProvider = new Provider<Integer>() {
+        @Override public Integer get() {
+          throw new UnsupportedOperationException();
+        }
+      };
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Guice.createInjector(module);
+
+    // If we don't throw an exception, we succeeded.
+  }
+
+  private static class InvalidBindableClass {
+    @Bind(to = String.class) Integer anInt;
+  }
+
+  public void testIncompatibleBindingTypeStackTraceHasUserFrame() {
+    Object instance = new InvalidBindableClass();
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(), "at " + InvalidBindableClass.class.getName() + " field anInt");
+    }
+  }
+
+  private static class InjectedNumberProvider implements Provider<Number> {
+    @Inject Integer anInt;
+
+    @Override public Number get() {
+      return anInt;
+    }
+  }
+
+  public void testBoundProvidersAreInjected() {
+    final Integer testValue = 1024;
+    Object instance = new Object() {
+      @Bind private Integer anInt = testValue;
+      @Bind private Provider<Number> aNumberProvider = new InjectedNumberProvider();
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue, injector.getInstance(Number.class));
+  }
+
+  public void testBoundInstancesAreInjected() {
+    final Integer testValue = 1024;
+    final InjectedNumberProvider testNumberProvider = new InjectedNumberProvider();
+    Object instance = new Object() {
+      @Bind private Integer anInt = testValue;
+      @Bind private InjectedNumberProvider aNumberProvider = testNumberProvider;
+    };
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Guice.createInjector(module);
+
+    assertEquals(testValue, testNumberProvider.anInt);
+  }
+
+  private static class InvalidBindableSubclass extends InvalidBindableClass {}
+
+  public void testClassIsPrintedInErrorsWhenCauseIsSuperclass() {
+    Object instance = new InvalidBindableSubclass();
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+
+    try {
+      Guice.createInjector(module);
+    } catch (CreationException e) {
+      assertContains(
+          e.getMessage(),
+          "Requested binding type \"java.lang.String\" is not assignable from field binding type "
+          + "\"java.lang.Integer\"");
+    }
+  }
+
+  private static class FieldBindableSubclass2 extends FieldBindableClass {
+    @Bind Number aNumber;
+
+    FieldBindableSubclass2(Integer anInt, Number aNumber) {
+      super(anInt);
+      this.aNumber = aNumber;
+    }
+  }
+
+  public void testFieldsAreBoundFromFullClassHierarchy() {
+    final Integer testValue1 = 1024, testValue2 = 2048;
+    FieldBindableSubclass2 instance = new FieldBindableSubclass2(testValue1, testValue2);
+
+    BoundFieldModule module = BoundFieldModule.of(instance);
+    Injector injector = Guice.createInjector(module);
+
+    assertEquals(testValue1, injector.getInstance(Integer.class));
+    assertEquals(testValue2, injector.getInstance(Number.class));
+  }
+
+  static final class LazyClass {
+    @Bind(lazy = true) Integer foo = 1;
+  }
+
+  public void testFieldBound_lazy() {
+    LazyClass asProvider = new LazyClass();
+    Injector injector = Guice.createInjector(BoundFieldModule.of(asProvider));
+    assertEquals(1, injector.getInstance(Integer.class).intValue());
+    asProvider.foo++;
+    assertEquals(2, injector.getInstance(Integer.class).intValue());
+  }
+
+  public void testFieldBound_lazy_rejectNull() {
+    LazyClass asProvider = new LazyClass();
+    Injector injector = Guice.createInjector(BoundFieldModule.of(asProvider));
+    assertEquals(1, injector.getInstance(Integer.class).intValue());
+    asProvider.foo = null;
+    try {
+      injector.getInstance(Integer.class);
+      fail();
+    } catch (ProvisionException e) {
+      assertContains(e.getMessage(),
+          "Binding to null values is not allowed. "
+          + "Use Providers.of(null) if this is your intended behavior.");
+    }
+  }
+
+  static final class LazyProviderClass {
+    @Bind(lazy = true) Provider<Integer> foo = Providers.of(null);
+  }
+
+  public void testFieldBoundAsProvider_rejectProvider() {
+    LazyProviderClass asProvider = new LazyProviderClass();
+    try {
+      Guice.createInjector(BoundFieldModule.of(asProvider));
+      fail();
+    } catch (CreationException e) {
+      assertContains(e.getMessage(), "'lazy' is incompatible with Provider valued fields");
+    }
+  }
+}
diff --git a/extensions/throwingproviders/build.properties b/extensions/throwingproviders/build.properties
new file mode 100644
index 0000000..3b5d5a8
--- /dev/null
+++ b/extensions/throwingproviders/build.properties
@@ -0,0 +1,7 @@
+lib.dir=../../lib
+src.dir=src
+test.dir=test
+build.dir=build
+test.class=com.google.inject.throwingproviders.ThrowingProviderBinderTest
+module=com.google.inject.throwingproviders
+fragment=true
diff --git a/extensions/throwingproviders/build.xml b/extensions/throwingproviders/build.xml
new file mode 100644
index 0000000..d123cf6
--- /dev/null
+++ b/extensions/throwingproviders/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="guice-throwingproviders" basedir="." default="jar">
+
+  <import file="../../common.xml"/>
+  
+  <path id="compile.classpath">
+    <fileset dir="${lib.dir}" includes="*.jar"/>
+    <fileset dir="${lib.dir}/build" includes="*.jar"/>
+    <pathelement path="../../build/classes"/>
+  </path>
+
+  <target name="jar" depends="compile, manifest" description="Build jar.">
+    <jar destfile="${build.dir}/${ant.project.name}-${version}.jar"
+        manifest="${build.dir}/META-INF/MANIFEST.MF">
+      <fileset dir="${build.dir}/classes" />
+    </jar>
+  </target>
+
+</project>
diff --git a/extensions/throwingproviders/pom.xml b/extensions/throwingproviders/pom.xml
new file mode 100644
index 0000000..472c107
--- /dev/null
+++ b/extensions/throwingproviders/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.inject.extensions</groupId>
+    <artifactId>extensions-parent</artifactId>
+    <version>4.0</version>
+  </parent>
+
+  <artifactId>guice-throwingproviders</artifactId>
+
+  <name>Google Guice - Extensions - ThrowingProviders</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>**/TestScope*</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java
new file mode 100644
index 0000000..ca5ab77
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java
@@ -0,0 +1,106 @@
+/**
+ * Copyright (C) 2012 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.inject.throwingproviders;
+
+import com.google.inject.Binder;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.Annotations;
+import com.google.inject.internal.Errors;
+import com.google.inject.spi.Message;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
+
+/**
+ * Utilities for the throwing provider module.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+class CheckedProvideUtils {
+  
+  private CheckedProvideUtils() {}
+  
+  private static final String CONSTRUCTOR_RULES =
+      "Classes must have either one (and only one) constructor annotated with @ThrowingInject.";
+  
+  @SuppressWarnings("unchecked") // safe because it's a constructor of the typeLiteral
+  static <T> Constructor<? extends T> findThrowingConstructor(
+      TypeLiteral<? extends T> typeLiteral, Binder binder) {
+    
+    Class<?> rawType = typeLiteral.getRawType();
+    Errors errors = new Errors(rawType);
+    Constructor<?> cxtor = null;
+    for (Constructor<?> constructor : rawType.getDeclaredConstructors()) {
+      if (constructor.isAnnotationPresent(ThrowingInject.class)) {
+        if (cxtor != null) {
+          errors.addMessage("%s has more than one constructor annotated with @ThrowingInject. "
+              + CONSTRUCTOR_RULES, rawType);
+        }
+
+        cxtor = constructor;
+        Annotation misplacedBindingAnnotation = Annotations.findBindingAnnotation(
+            errors, cxtor, ((AnnotatedElement) cxtor).getAnnotations());
+        if (misplacedBindingAnnotation != null) {
+          errors.misplacedBindingAnnotation(cxtor, misplacedBindingAnnotation);
+        }
+      }
+    }
+    
+    if (cxtor == null) {
+      errors.addMessage(
+          "Could not find a suitable constructor in %s. " + CONSTRUCTOR_RULES, rawType);
+    }
+
+    for (Message msg : errors.getMessages()) {
+      binder.addError(msg);
+    }
+    return (Constructor<? extends T>) cxtor;
+  }
+  
+  /** Adds errors to the binder if the exceptions aren't valid. */
+  static void validateExceptions(Binder binder,
+      Iterable<TypeLiteral<?>> actualExceptionTypes,
+      Iterable<Class<? extends Throwable>> expectedExceptionTypes,
+      Class<? extends CheckedProvider> checkedProvider) {
+    // Validate the exceptions in the method match the exceptions
+    // in the CheckedProvider.
+    for (TypeLiteral<?> exType : actualExceptionTypes) {
+      Class<?> exActual = exType.getRawType();
+      // Ignore runtime exceptions & errors.
+      if (RuntimeException.class.isAssignableFrom(exActual)
+          || Error.class.isAssignableFrom(exActual)) {
+        continue;
+      }
+
+      boolean notAssignable = true;
+      for (Class<? extends Throwable> exExpected : expectedExceptionTypes) {
+        if (exExpected.isAssignableFrom(exActual)) {
+          notAssignable = false;
+          break;
+        }
+      }
+      if (notAssignable) {
+        binder.addError(
+            "%s is not compatible with the exceptions (%s) declared in " 
+            + "the CheckedProvider interface (%s)",
+            exActual, expectedExceptionTypes, checkedProvider);
+      }
+    }
+  }
+
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvider.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvider.java
new file mode 100644
index 0000000..3ee2260
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvider.java
@@ -0,0 +1,39 @@
+/**
+ * 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 com.google.inject.throwingproviders;
+
+/**
+ * Alternative to the Guice {@link com.google.inject.Provider} that throws
+ * a checked Exception. Users may not inject {@code T} directly.
+ *
+ * <p>This interface must be extended to use application-specific exception types.
+ * Such subinterfaces may not define new methods, but may narrow the exception type.
+ * <pre>
+ * public interface RemoteProvider&lt;T&gt; extends CheckedProvider&lt;T&gt; { 
+ *   T get() throws CustomExceptionOne, CustomExceptionTwo;
+ * }
+ * </pre>
+ *
+ * <p>When this type is bound using {@link ThrowingProviderBinder}, the value returned
+ * or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get}
+ * will invoked at most once within each scope.
+ * 
+ * @since 3.0
+ */
+public interface CheckedProvider<T> {
+  T get() throws Exception;
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java
new file mode 100644
index 0000000..a76d64c
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright (C) 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.inject.throwingproviders;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Exposed;
+import com.google.inject.Key;
+import com.google.inject.PrivateBinder;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.ScopedBindingBuilder;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A provider that invokes a method and returns its result.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ */
+class CheckedProviderMethod<T> implements CheckedProvider<T>, HasDependencies {
+  private final Key<T> key;
+  private final Class<? extends Annotation> scopeAnnotation;
+  private final Object instance;
+  private final Method method;
+  private final ImmutableSet<Dependency<?>> dependencies;
+  private final List<Provider<?>> parameterProviders;
+  private final boolean exposed;
+  private final Class<? extends CheckedProvider> checkedProvider;
+  private final List<TypeLiteral<?>> exceptionTypes;
+  private final boolean scopeExceptions;
+
+  CheckedProviderMethod(
+      Key<T> key,
+      Method method,
+      Object instance,
+      ImmutableSet<Dependency<?>> dependencies,
+      List<Provider<?>> parameterProviders,
+      Class<? extends Annotation> scopeAnnotation,
+      Class<? extends CheckedProvider> checkedProvider,
+      List<TypeLiteral<?>> exceptionTypes,
+      boolean scopeExceptions) {
+    this.key = key;
+    this.scopeAnnotation = scopeAnnotation;
+    this.instance = instance;
+    this.dependencies = dependencies;
+    this.method = method;
+    this.parameterProviders = parameterProviders;
+    this.exposed = method.isAnnotationPresent(Exposed.class);
+    this.checkedProvider = checkedProvider;
+    this.exceptionTypes = exceptionTypes;
+    this.scopeExceptions = scopeExceptions;
+
+    method.setAccessible(true);
+  }
+
+  void configure(Binder binder) {
+    binder = binder.withSource(method);
+
+    SecondaryBinder<?, ?> sbinder = 
+        ThrowingProviderBinder.create(binder)
+          .bind(checkedProvider, key.getTypeLiteral());
+    if(key.getAnnotation() != null) {
+      sbinder = sbinder.annotatedWith(key.getAnnotation());
+    } else if(key.getAnnotationType() != null) {
+      sbinder = sbinder.annotatedWith(key.getAnnotationType());
+    }
+    sbinder.scopeExceptions(scopeExceptions);
+    ScopedBindingBuilder sbbuilder = sbinder.toProviderMethod(this);
+    if(scopeAnnotation != null) {
+      sbbuilder.in(scopeAnnotation);
+    }
+
+    if (exposed) {
+      // the cast is safe 'cause the only binder we have implements PrivateBinder. If there's a
+      // misplaced @Exposed, calling this will add an error to the binder's error queue
+      ((PrivateBinder) binder).expose(sbinder.getKey());
+    }
+    
+    CheckedProvideUtils.validateExceptions(
+        binder, exceptionTypes, sbinder.getExceptionTypes(), checkedProvider);
+  }
+
+  public T get() throws Exception {
+    Object[] parameters = new Object[parameterProviders.size()];
+    for (int i = 0; i < parameters.length; i++) {
+      parameters[i] = parameterProviders.get(i).get();
+    }
+
+    try {
+      // We know this cast is safe becase T is the method's return type.
+      @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" })
+      T result = (T) method.invoke(instance, parameters);
+      return result;
+    } catch (IllegalAccessException e) {
+      throw new AssertionError(e);
+    } catch (InvocationTargetException e) {
+      Throwable t = e.getCause();
+      if(t instanceof Exception) {
+        throw (Exception)t;
+      } else if(t instanceof Error) {
+        throw (Error)t;
+      } else {
+        throw new IllegalStateException(t);
+      }
+    }
+  }
+
+  public Set<Dependency<?>> getDependencies() {
+    return dependencies;
+  }
+
+  @Override public String toString() {
+    return "@CheckedProvides " + StackTraceElements.forMember(method);
+  }
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java
new file mode 100644
index 0000000..f88c507
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java
@@ -0,0 +1,158 @@
+/**
+ * Copyright (C) 2010 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.inject.throwingproviders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.Annotations;
+import com.google.inject.internal.Errors;
+import com.google.inject.internal.UniqueAnnotations;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Message;
+import com.google.inject.util.Modules;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * Creates bindings to methods annotated with {@literal @}{@link CheckedProvides}. Use the scope
+ * and binding annotations on the provider method to configure the binding.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+final class CheckedProviderMethodsModule implements Module {
+  private static final Key<Logger> LOGGER_KEY = Key.get(Logger.class);
+
+  private final Object delegate;
+  private final TypeLiteral<?> typeLiteral;
+
+  private CheckedProviderMethodsModule(Object delegate) {
+    this.delegate = checkNotNull(delegate, "delegate");
+    this.typeLiteral = TypeLiteral.get(this.delegate.getClass());
+  }
+
+  /**
+   * Returns a module which creates bindings for provider methods from the given module.
+   */
+  static Module forModule(Module module) {
+    // avoid infinite recursion, since installing a module always installs itself
+    if (module instanceof CheckedProviderMethodsModule) {
+      return Modules.EMPTY_MODULE;
+    }
+
+    return new CheckedProviderMethodsModule(module);
+  }
+  
+  public synchronized void configure(Binder binder) {
+    for (CheckedProviderMethod<?> throwingProviderMethod : getProviderMethods(binder)) {
+      throwingProviderMethod.configure(binder);
+    }
+  }
+
+  List<CheckedProviderMethod<?>> getProviderMethods(Binder binder) {
+    List<CheckedProviderMethod<?>> result = Lists.newArrayList();
+    for (Class<?> c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) {
+      for (Method method : c.getDeclaredMethods()) {
+        CheckedProvides checkedProvides = method.getAnnotation(CheckedProvides.class);
+        if(checkedProvides != null) {
+          result.add(createProviderMethod(binder, method, checkedProvides));
+        }
+      }
+    }
+    return result;
+  }
+
+  <T> CheckedProviderMethod<T> createProviderMethod(Binder binder, final Method method,
+      CheckedProvides checkedProvides) {
+    @SuppressWarnings("rawtypes")
+    Class<? extends CheckedProvider> throwingProvider = checkedProvides.value();
+    binder = binder.withSource(method);
+    Errors errors = new Errors(method);
+
+    // prepare the parameter providers
+    List<Dependency<?>> dependencies = Lists.newArrayList();
+    List<Provider<?>> parameterProviders = Lists.newArrayList();
+    List<TypeLiteral<?>> parameterTypes = typeLiteral.getParameterTypes(method);
+    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+    for (int i = 0; i < parameterTypes.size(); i++) {
+      Key<?> key = getKey(errors, parameterTypes.get(i), method, parameterAnnotations[i]);
+      if (key.equals(LOGGER_KEY)) {
+        // If it was a Logger, change the key to be unique & bind it to a
+        // provider that provides a logger with a proper name.
+        // This solves issue 482 (returning a new anonymous logger on every call exhausts memory)
+        Key<Logger> loggerKey = Key.get(Logger.class, UniqueAnnotations.create());
+        binder.bind(loggerKey).toProvider(new LogProvider(method));
+        key = loggerKey;
+      }
+      dependencies.add(Dependency.get(key));
+      parameterProviders.add(binder.getProvider(key));        
+    }
+
+    @SuppressWarnings("unchecked") // Define T as the method's return type.
+    TypeLiteral<T> returnType = (TypeLiteral<T>) typeLiteral.getReturnType(method);
+    List<TypeLiteral<?>> exceptionTypes = typeLiteral.getExceptionTypes(method);
+
+    Key<T> key = getKey(errors, returnType, method, method.getAnnotations());
+    Class<? extends Annotation> scopeAnnotation
+        = Annotations.findScopeAnnotation(errors, method.getAnnotations());
+
+    for (Message message : errors.getMessages()) {
+      binder.addError(message);
+    }
+
+    return new CheckedProviderMethod<T>(key, method, delegate, ImmutableSet.copyOf(dependencies),
+        parameterProviders, scopeAnnotation, throwingProvider, exceptionTypes, 
+        checkedProvides.scopeExceptions()); 
+  }
+
+  <T> Key<T> getKey(Errors errors, TypeLiteral<T> type, Member member, Annotation[] annotations) {
+    Annotation bindingAnnotation = Annotations.findBindingAnnotation(errors, member, annotations);
+    return bindingAnnotation == null ? Key.get(type) : Key.get(type, bindingAnnotation);
+  }
+
+  @Override public boolean equals(Object o) {
+    return o instanceof CheckedProviderMethodsModule
+        && ((CheckedProviderMethodsModule) o).delegate == delegate;
+  }
+
+  @Override public int hashCode() {
+    return delegate.hashCode();
+  }
+  
+  /** A provider that returns a logger based on the method name. */
+  private static final class LogProvider implements Provider<Logger> {
+    private final String name;
+    
+    public LogProvider(Method method) {
+      this.name = method.getDeclaringClass().getName() + "." + method.getName();
+    }
+    
+    public Logger get() {
+      return Logger.getLogger(name);
+    }
+  }
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java
new file mode 100644
index 0000000..79df84d
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2012 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.inject.throwingproviders;
+
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder;
+
+/**
+ * A checked provider with dependencies, so {@link HasDependencies} can be implemented
+ * when using the {@link SecondaryBinder#using} methods.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ */
+interface CheckedProviderWithDependencies<T> extends CheckedProvider<T>, HasDependencies {
+
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvides.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvides.java
new file mode 100644
index 0000000..b401620
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvides.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2010 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.inject.throwingproviders;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates methods of a {@link com.google.inject.Module} to create a
+ * {@link CheckedProvider} method binding that can throw exceptions. The
+ * method's return type is bound to a {@link CheckedProvider} that can be
+ * injected. Guice will pass dependencies to the method as parameters. Install
+ * {@literal @}CheckedProvides methods by using
+ * {@link ThrowingProviderBinder#forModule(com.google.inject.Module)} on the
+ * module where the methods are declared.
+ * 
+ * @author sameb@google.com (Sam Berlin)
+ * @since 3.0
+ */
+@Documented @Target(METHOD) @Retention(RUNTIME)
+public @interface CheckedProvides {
+  
+  /**
+   * The interface that provides this value, a subinterface of {@link CheckedProvider}.
+   */
+  Class<? extends CheckedProvider> value();
+
+  /**
+   * Whether exceptions should be put into the Guice scope.
+   * Default behavior is that exceptions are scoped.
+   *
+   * @since 4.0
+   */
+  boolean scopeExceptions() default true;  
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingInject.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingInject.java
new file mode 100644
index 0000000..445d697
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingInject.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2012 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.inject.throwingproviders;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.Inject;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * A version of {@literal @}{@link Inject} designed for ThrowingProviders.  Use by:
+ * <pre><code>ThrowingProviderBinder.create(binder())
+ *    .bind(RemoteProvider.class, Customer.class)
+ *    .providing(CustomerImpl.class);
+ * </code></pre>
+ * where CustomerImpl has a constructor annotated with ThrowingInject.
+ *
+ * @author sameb@google.com (Sam Berlin)
+ * @since 4.0
+ */
+@Target({ CONSTRUCTOR })
+@Retention(RUNTIME)
+@Documented
+public @interface ThrowingInject {
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProvider.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProvider.java
new file mode 100644
index 0000000..4ecab4d
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProvider.java
@@ -0,0 +1,40 @@
+/**
+ * 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 com.google.inject.throwingproviders;
+
+/**
+ * Alternative to the Guice {@link com.google.inject.Provider} that throws
+ * a checked Exception. Users may not inject {@code T} directly.
+ *
+ * <p>This interface must be extended to use application-specific exception types.
+ * Such subinterfaces may not define new methods:
+ * <pre>
+ * public interface RemoteProvider&lt;T&gt; extends ThrowingProvider&lt;T, RemoteException&gt; { }
+ * </pre>
+ *
+ * <p>When this type is bound using {@link ThrowingProviderBinder}, the value returned
+ * or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get}
+ * will invoked at most once within each scope.
+ *
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @deprecated use {@link CheckedProvider} instead.
+ */
+@Deprecated
+public interface ThrowingProvider<T,E extends Exception> extends CheckedProvider<T> {
+  T get() throws E;
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java
new file mode 100644
index 0000000..546a242
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java
@@ -0,0 +1,569 @@
+/**
+ * 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 com.google.inject.throwingproviders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.ScopedBindingBuilder;
+import com.google.inject.internal.UniqueAnnotations;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.ProviderWithDependencies;
+import com.google.inject.util.Types;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * <p>Builds a binding for a {@link CheckedProvider}.
+ * 
+ * <p>You can use a fluent API and custom providers:
+ * <pre><code>ThrowingProviderBinder.create(binder())
+ *    .bind(RemoteProvider.class, Customer.class)
+ *    .to(RemoteCustomerProvider.class)
+ *    .in(RequestScope.class);
+ * </code></pre>
+ * or, you can use throwing provider methods:
+ * <pre><code>class MyModule extends AbstractModule {
+ *   configure() {
+ *     ThrowingProviderBinder.install(this, binder());
+ *   }
+ *   
+ *   {@literal @}CheckedProvides(RemoteProvider.class)
+ *   {@literal @}RequestScope
+ *   Customer provideCustomer(FlakyCustomerCreator creator) throws RemoteException {
+ *     return creator.getCustomerOrThrow();
+ *   }
+ * }
+ * </code></pre>
+ * You also can declare that a CheckedProvider construct
+ * a particular class whose constructor throws an exception:
+ * <pre><code>ThrowingProviderBinder.create(binder())
+ *    .bind(RemoteProvider.class, Customer.class)
+ *    .providing(CustomerImpl.class)
+ *    .in(RequestScope.class);
+ * </code></pre>
+ * 
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class ThrowingProviderBinder {
+
+  private static final TypeLiteral<CheckedProvider<?>> CHECKED_PROVIDER_TYPE
+      = new TypeLiteral<CheckedProvider<?>>() { };
+
+  private static final TypeLiteral<CheckedProviderMethod<?>> CHECKED_PROVIDER_METHOD_TYPE
+      = new TypeLiteral<CheckedProviderMethod<?>>() { };
+
+  private final Binder binder;
+
+  private ThrowingProviderBinder(Binder binder) {
+    this.binder = binder;
+  }
+
+  public static ThrowingProviderBinder create(Binder binder) {
+    return new ThrowingProviderBinder(binder.skipSources(
+        ThrowingProviderBinder.class,
+        ThrowingProviderBinder.SecondaryBinder.class));
+  }
+  
+  /**
+   * Returns a module that installs {@literal @}{@link CheckedProvides} methods.
+   * 
+   * @since 3.0
+   */
+  public static Module forModule(Module module) {
+    return CheckedProviderMethodsModule.forModule(module);
+  }
+  
+  /**
+   * @deprecated Use {@link #bind(Class, Class)} or {@link #bind(Class, TypeLiteral)} instead. 
+   */
+  @Deprecated
+  public <P extends CheckedProvider> SecondaryBinder<P, ?> 
+      bind(Class<P> interfaceType, Type clazz) {
+    return new SecondaryBinder<P, Object>(interfaceType, clazz);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public <P extends CheckedProvider, T> SecondaryBinder<P, T> 
+      bind(Class<P> interfaceType, Class<T> clazz) {
+    return new SecondaryBinder<P, T>(interfaceType, clazz);
+  }
+  
+  /**
+   * @since 4.0
+   */
+  public <P extends CheckedProvider, T> SecondaryBinder<P, T> 
+      bind(Class<P> interfaceType, TypeLiteral<T> typeLiteral) {
+    return new SecondaryBinder<P, T>(interfaceType, typeLiteral.getType());
+  }
+
+  public class SecondaryBinder<P extends CheckedProvider, T> {
+    private final Class<P> interfaceType;
+    private final Type valueType;
+    private final List<Class<? extends Throwable>> exceptionTypes;
+    private final boolean valid;
+
+    private Class<? extends Annotation> annotationType;
+    private Annotation annotation;
+    private Key<P> interfaceKey;
+    private boolean scopeExceptions = true;
+
+    public SecondaryBinder(Class<P> interfaceType, Type valueType) {
+      this.interfaceType = checkNotNull(interfaceType, "interfaceType");
+      this.valueType = checkNotNull(valueType, "valueType");
+      if(checkInterface()) {
+        this.exceptionTypes = getExceptionType(interfaceType);
+        valid = true;
+      } else {
+        valid = false;
+        this.exceptionTypes = ImmutableList.of();
+      }      
+    }
+    
+    List<Class<? extends Throwable>> getExceptionTypes() {
+      return exceptionTypes;
+    }
+    
+    Key<P> getKey() {
+      return interfaceKey;
+    }
+
+    public SecondaryBinder<P, T> annotatedWith(Class<? extends Annotation> annotationType) {
+      if (!(this.annotationType == null && this.annotation == null)) {
+        throw new IllegalStateException("Cannot set annotation twice");
+      }
+      this.annotationType = annotationType;
+      return this;
+    }
+
+    public SecondaryBinder<P, T> annotatedWith(Annotation annotation) {
+      if (!(this.annotationType == null && this.annotation == null)) {
+        throw new IllegalStateException("Cannot set annotation twice");
+      }
+      this.annotation = annotation;
+      return this;
+    }
+
+    /**
+     * Determines if exceptions should be scoped. By default exceptions are scoped.
+     *
+     * @param scopeExceptions whether exceptions should be scoped.
+     * @since 4.0
+     */
+    public SecondaryBinder<P, T> scopeExceptions(boolean scopeExceptions) {
+      this.scopeExceptions = scopeExceptions;
+      return this;
+    }
+    
+    public ScopedBindingBuilder to(P target) {
+      Key<P> targetKey = Key.get(interfaceType, UniqueAnnotations.create());
+      binder.bind(targetKey).toInstance(target);
+      return to(targetKey);
+    }
+    
+    public ScopedBindingBuilder to(Class<? extends P> targetType) {
+      return to(Key.get(targetType));
+    }
+
+    /** @since 4.0 */
+    public ScopedBindingBuilder providing(Class<? extends T> cxtorClass) {
+      return providing(TypeLiteral.get(cxtorClass));
+    }
+
+    /** @since 4.0 */
+    @SuppressWarnings("unchecked") // safe because this is the cxtor of the literal
+    public ScopedBindingBuilder providing(TypeLiteral<? extends T> cxtorLiteral) {     
+      // Find a constructor that has @ThrowingInject.
+      Constructor<? extends T> cxtor =
+          CheckedProvideUtils.findThrowingConstructor(cxtorLiteral, binder);
+
+      final Provider<T> typeProvider;
+      final Key<? extends T> typeKey;
+      // If we found an injection point, then bind the cxtor to a unique key
+      if (cxtor != null) {
+        // Validate the exceptions are consistent with the CheckedProvider interface.
+        CheckedProvideUtils.validateExceptions(
+            binder, cxtorLiteral.getExceptionTypes(cxtor), exceptionTypes, interfaceType);
+        
+        typeKey = Key.get(cxtorLiteral, UniqueAnnotations.create());
+        binder.bind(typeKey).toConstructor((Constructor) cxtor).in(Scopes.NO_SCOPE);
+        typeProvider = binder.getProvider((Key<T>) typeKey);
+      } else {
+        // never used, but need it assigned.
+        typeProvider = null;
+        typeKey = null;
+      }
+        
+      // Create a CheckedProvider that calls our cxtor
+      CheckedProvider<T> checkedProvider = new CheckedProviderWithDependencies<T>() {
+        @Override
+        public T get() throws Exception {
+          try {
+            return typeProvider.get();
+          } catch (ProvisionException pe) {
+            // Rethrow the provision cause as the actual exception
+            if (pe.getCause() instanceof Exception) {
+              throw (Exception) pe.getCause();
+            } else if (pe.getCause() instanceof Error) {
+              throw (Error) pe.getCause();
+            } else {
+              // If this failed because of multiple reasons (ie, more than
+              // one dependency failed due to scoping errors), then
+              // the ProvisionException won't have a cause, so we need
+              // to rethrow it as-is.
+              throw pe;
+            }
+          }
+        }
+        
+        @Override
+        public Set<Dependency<?>> getDependencies() {
+          return ImmutableSet.<Dependency<?>>of(Dependency.get(typeKey));
+        }
+      };
+      
+      Key<CheckedProvider<?>> targetKey = Key.get(CHECKED_PROVIDER_TYPE,
+          UniqueAnnotations.create());
+      binder.bind(targetKey).toInstance(checkedProvider);
+      return toInternal(targetKey);
+    }
+    
+    ScopedBindingBuilder toProviderMethod(CheckedProviderMethod<?> target) {
+      Key<CheckedProviderMethod<?>> targetKey = 
+          Key.get(CHECKED_PROVIDER_METHOD_TYPE, UniqueAnnotations.create());
+      binder.bind(targetKey).toInstance(target);
+
+      return toInternal(targetKey);
+    }
+
+    @SuppressWarnings("unchecked") // P only extends the raw type of CheckedProvider
+    public ScopedBindingBuilder to(Key<? extends P> targetKey) {
+      checkNotNull(targetKey, "targetKey");
+      return toInternal((Key<? extends CheckedProvider<?>>)targetKey);
+    }
+    
+    private ScopedBindingBuilder toInternal(final Key<? extends CheckedProvider<?>> targetKey) {
+      final Key<Result> resultKey = Key.get(Result.class, UniqueAnnotations.create());
+      // Note that this provider will behave like the final provider Guice creates.
+      // It will especially do scoping if the user adds that.
+      final Provider<Result> resultProvider = binder.getProvider(resultKey);
+      final Provider<? extends CheckedProvider<?>> targetProvider = binder.getProvider(targetKey);
+      interfaceKey = createKey();
+
+      // don't bother binding the proxy type if this is in an invalid state.
+      if(valid) {
+        binder.bind(interfaceKey).toProvider(new ProviderWithDependencies<P>() {
+          private final P instance = interfaceType.cast(Proxy.newProxyInstance(
+              interfaceType.getClassLoader(), new Class<?>[] { interfaceType },
+              new InvocationHandler() {
+                public Object invoke(Object proxy, Method method, Object[] args)
+                    throws Throwable {
+                  // Allow methods like .equals(..), .hashcode(..), .toString(..) to work.
+                  if (method.getDeclaringClass() == Object.class) {
+                    return method.invoke(this, args);
+                  }
+                  
+                  if (scopeExceptions) {
+                    return resultProvider.get().getOrThrow();
+                  } else {
+                    Result result;
+                    try {
+                      result = resultProvider.get();
+                    } catch (ProvisionException pe) {
+                      Throwable cause = pe.getCause();
+                      if (cause instanceof ResultException) {
+                        throw ((ResultException)cause).getCause();
+                      } else {
+                        throw pe;
+                      }
+                    }
+                    return result.getOrThrow();
+                  }
+                }
+              }));
+            
+            @Override
+            public P get() {
+              return instance;
+            }
+  
+            @Override
+            public Set<Dependency<?>> getDependencies() {
+              return ImmutableSet.<Dependency<?>>of(Dependency.get(resultKey));
+            }
+          });
+      }
+
+      // The provider is unscoped, but the user may apply a scope to it through the 
+      // ScopedBindingBuilder this returns.
+      return binder.bind(resultKey).toProvider(
+          createResultProvider(targetKey, targetProvider));
+    }
+
+    private ProviderWithDependencies<Result> createResultProvider(
+        final Key<? extends CheckedProvider<?>> targetKey,
+        final Provider<? extends CheckedProvider<?>> targetProvider) {
+      return new ProviderWithDependencies<Result>() {
+        @Override
+        public Result get() {
+          try {
+            return Result.forValue(targetProvider.get().get());
+          } catch (Exception e) {
+            for (Class<? extends Throwable> exceptionType : exceptionTypes) {
+              if (exceptionType.isInstance(e)) {
+                if (scopeExceptions) {
+                  return Result.forException(e);
+                } else {
+                  throw new ResultException(e);
+                }
+              }
+            }
+
+            if (e instanceof RuntimeException) {
+              throw (RuntimeException) e;
+            } else {
+              // this should never happen
+              throw new RuntimeException(e);
+            }
+          }
+        }
+
+        @Override
+        public Set<Dependency<?>> getDependencies() {
+          return ImmutableSet.<Dependency<?>>of(Dependency.get(targetKey));
+        }
+      };
+    }
+    
+    /**
+     * Returns the exception type declared to be thrown by the get method of
+     * {@code interfaceType}.
+     */
+    private List<Class<? extends Throwable>> getExceptionType(Class<P> interfaceType) {
+      try {
+        Method getMethod = interfaceType.getMethod("get");
+        List<TypeLiteral<?>> exceptionLiterals =
+            TypeLiteral.get(interfaceType).getExceptionTypes(getMethod);
+        List<Class<? extends Throwable>> results = Lists.newArrayList();
+        for (TypeLiteral<?> exLiteral : exceptionLiterals) {
+          results.add(exLiteral.getRawType().asSubclass(Throwable.class));
+        }
+        return results;
+      } catch (SecurityException e) {
+        throw new IllegalStateException("Not allowed to inspect exception types", e);
+      } catch (NoSuchMethodException e) {
+        throw new IllegalStateException("No 'get'method available", e);
+      }
+    }
+
+    private boolean checkInterface() {
+      if(!checkArgument(interfaceType.isInterface(),
+         "%s must be an interface", interfaceType.getName())) {
+        return false;
+      }
+      if(!checkArgument(interfaceType.getGenericInterfaces().length == 1,
+          "%s must extend CheckedProvider (and only CheckedProvider)",
+          interfaceType)) {
+        return false;
+      }
+      
+      boolean tpMode = interfaceType.getInterfaces()[0] == ThrowingProvider.class;      
+      if(!tpMode) {
+        if(!checkArgument(interfaceType.getInterfaces()[0] == CheckedProvider.class,
+            "%s must extend CheckedProvider (and only CheckedProvider)",
+            interfaceType)) {
+          return false;
+        }
+      }
+
+      // Ensure that T is parameterized and unconstrained.
+      ParameterizedType genericThrowingProvider
+          = (ParameterizedType) interfaceType.getGenericInterfaces()[0];
+      if (interfaceType.getTypeParameters().length == 1) {
+        String returnTypeName = interfaceType.getTypeParameters()[0].getName();
+        Type returnType = genericThrowingProvider.getActualTypeArguments()[0];
+        if(!checkArgument(returnType instanceof TypeVariable,
+            "%s does not properly extend CheckedProvider, the first type parameter of CheckedProvider (%s) is not a generic type",
+            interfaceType, returnType)) {
+          return false;
+        }
+        if(!checkArgument(returnTypeName.equals(((TypeVariable) returnType).getName()),
+            "The generic type (%s) of %s does not match the generic type of CheckedProvider (%s)",
+            returnTypeName, interfaceType, ((TypeVariable)returnType).getName())) {
+          return false;
+        }
+      } else {
+        if(!checkArgument(interfaceType.getTypeParameters().length == 0,
+            "%s has more than one generic type parameter: %s",
+            interfaceType, Arrays.asList(interfaceType.getTypeParameters()))) {
+          return false;
+        }
+        if(!checkArgument(genericThrowingProvider.getActualTypeArguments()[0].equals(valueType),
+            "%s expects the value type to be %s, but it was %s",
+            interfaceType, genericThrowingProvider.getActualTypeArguments()[0], valueType)) {
+          return false;
+        }
+      }
+
+      if(tpMode) { // only validate exception in ThrowingProvider mode.
+        Type exceptionType = genericThrowingProvider.getActualTypeArguments()[1];
+        if(!checkArgument(exceptionType instanceof Class,
+            "%s has the wrong Exception generic type (%s) when extending CheckedProvider",
+            interfaceType, exceptionType)) {
+          return false;
+        }
+      }
+      
+      // Skip synthetic/bridge methods because java8 generates
+      // a default method on the interface w/ the superinterface type that
+      // just delegates directly to the overridden method.
+      List<Method> declaredMethods = FluentIterable
+          .from(Arrays.asList(interfaceType.getDeclaredMethods()))
+          .filter(NotSyntheticOrBridgePredicate.INSTANCE)
+          .toList();
+      if (declaredMethods.size() == 1) {
+        Method method = declaredMethods.get(0);
+        if(!checkArgument(method.getName().equals("get"),
+            "%s may not declare any new methods, but declared %s",
+            interfaceType, method)) {
+          return false;
+        }
+        if(!checkArgument(method.getParameterTypes().length == 0,
+            "%s may not declare any new methods, but declared %s",
+            interfaceType, method.toGenericString())) {
+          return false;
+        }
+      } else {
+        if(!checkArgument(declaredMethods.isEmpty(),
+            "%s may not declare any new methods, but declared %s",
+            interfaceType, Arrays.asList(interfaceType.getDeclaredMethods()))) {
+          return false;
+        }
+      }
+      
+      return true;
+    }
+
+    private boolean checkArgument(boolean condition,
+        String messageFormat, Object... args) {
+      if (!condition) {
+        binder.addError(messageFormat, args);
+        return false;
+      } else {
+        return true;
+      }
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private Key<P> createKey() {
+      TypeLiteral<P> typeLiteral;
+      if (interfaceType.getTypeParameters().length == 1) {
+        ParameterizedType type = Types.newParameterizedTypeWithOwner(
+            interfaceType.getEnclosingClass(), interfaceType, valueType);
+        typeLiteral = (TypeLiteral<P>) TypeLiteral.get(type);
+      } else {
+        typeLiteral = TypeLiteral.get(interfaceType);
+      }
+
+      if (annotation != null) {
+        return Key.get(typeLiteral, annotation);
+        
+      } else if (annotationType != null) {
+        return Key.get(typeLiteral, annotationType);
+        
+      } else {
+        return Key.get(typeLiteral);
+      }
+    }
+  }
+
+  /**
+   * Represents the returned value from a call to {@link CheckedProvider#get()}. This is the value
+   * that will be scoped by Guice.
+   */
+  static class Result implements Serializable {
+    private static final long serialVersionUID = 0L;
+
+    private final Object value;
+    private final Exception exception;
+
+    private Result(Object value, Exception exception) {
+      this.value = value;
+      this.exception = exception;
+    }
+
+    public static Result forValue(Object value) {
+      return new Result(value, null);
+    }
+
+    public static Result forException(Exception e) {
+      return new Result(null, e);
+    }
+    
+    public Object getOrThrow() throws Exception {
+      if (exception != null) {
+        throw exception;
+      } else {
+        return value;
+      }
+    }
+  }
+
+  /**
+   * RuntimeException class to wrap exceptions from the checked provider.
+   * The regular guice provider can throw it and the checked provider proxy extracts
+   * the underlying exception and rethrows it.
+   */
+  private static class ResultException extends RuntimeException {
+    ResultException(Exception cause) {
+      super(cause);
+    }
+  }
+  
+  private static class NotSyntheticOrBridgePredicate implements Predicate<Method> {
+    static NotSyntheticOrBridgePredicate INSTANCE = new NotSyntheticOrBridgePredicate();
+    @Override public boolean apply(Method input) {
+      return !input.isBridge() && !input.isSynthetic();
+    }
+  }
+}
diff --git a/extensions/throwingproviders/src/com/google/inject/throwingproviders/package-info.java b/extensions/throwingproviders/src/com/google/inject/throwingproviders/package-info.java
new file mode 100644
index 0000000..29361f7
--- /dev/null
+++ b/extensions/throwingproviders/src/com/google/inject/throwingproviders/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Extension for injecting objects that may throw at provision time; this extension requires {@code
+ * guice-throwingproviders.jar}.
+ */
+package com.google.inject.throwingproviders;
diff --git a/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMethodsModuleTest.java b/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMethodsModuleTest.java
new file mode 100644
index 0000000..b7a8335
--- /dev/null
+++ b/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMethodsModuleTest.java
@@ -0,0 +1,195 @@
+/**
+ * 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 com.google.inject.throwingproviders;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Exposed;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.PrivateModule;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.net.BindException;
+import java.rmi.RemoteException;
+
+/**
+ * Test methods for {@link CheckedProviderMethodsModule}.
+ */
+public class CheckedProviderMethodsModuleTest extends TestCase {
+
+  private final TypeLiteral<RpcProvider<String>> rpcProviderOfString
+      = new TypeLiteral<RpcProvider<String>>() { };
+  private final TypeLiteral<RpcProvider<Integer>> rpcProviderOfInteger
+      = new TypeLiteral<RpcProvider<Integer>>() { };
+  private final TypeLiteral<RpcProvider<Long>> rpcProviderOfLong
+      = new TypeLiteral<RpcProvider<Long>>() { };
+  private final TypeLiteral<RpcProvider<Float>> rpcProviderOfFloat
+      = new TypeLiteral<RpcProvider<Float>>() { };
+  private final TypeLiteral<RpcProvider<Pair<Double, String>>> rpcProviderOfPair
+      = new TypeLiteral<RpcProvider<Pair<Double, String>>>() { };
+
+  private final TestScope testScope = new TestScope();
+
+  interface RpcProvider<T> extends CheckedProvider<T> {
+    T get() throws RemoteException, BindException;
+  }
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @BindingAnnotation
+  @interface TestAnnotation {
+  }
+
+  class TestModule extends AbstractModule {
+
+    private int nextIntToReturn = 100;
+
+    @Override
+    protected void configure() {
+      bindScope(TestScope.Scoped.class, testScope);
+      install(ThrowingProviderBinder.forModule(this));
+      install(new TestPrivateModule());
+    }
+
+    @CheckedProvides(RpcProvider.class)
+    String getSomeStringFromServer() {
+      return "Works";
+    }
+
+    @CheckedProvides(RpcProvider.class) @TestScope.Scoped
+    int getSomeIntegerFromServer() {
+      return nextIntToReturn;
+    }
+
+    @CheckedProvides(RpcProvider.class) @TestAnnotation
+    long getSomeLongFromServer() {
+      return 0xffL;
+    }
+
+    @Provides
+    double getSomeDouble() {
+      return 2.0d;
+    }
+
+    @CheckedProvides(RpcProvider.class)
+    Pair<Double, String> getSomePair(Double input) {
+      return new Pair<Double, String>(input * 2, "foo");
+    }
+
+    @CheckedProvides(RpcProvider.class)
+    float getFloat() throws BindException {
+      throw new BindException("foo");
+    }
+
+    void setNextIntToReturn(int next) {
+      nextIntToReturn = next;
+    }
+  }
+
+  class TestPrivateModule extends PrivateModule {
+
+    @Override
+    protected void configure() {
+      install(ThrowingProviderBinder.forModule(this));
+    }
+
+    @CheckedProvides(RpcProvider.class) @Named("fruit") @Exposed
+    String provideApples() {
+      return "apple";
+    }
+  }
+  
+
+  public void testNoAnnotationNoScope() throws BindException, RemoteException {
+    Injector injector = Guice.createInjector(new TestModule());
+    RpcProvider<String> provider = injector
+        .getInstance(Key.get(rpcProviderOfString));
+    assertEquals("Works", provider.get());
+  }
+
+  public void testWithScope() throws BindException, RemoteException {
+    TestModule testModule = new TestModule();
+    Injector injector = Guice.createInjector(testModule);
+    RpcProvider<Integer> provider = injector
+        .getInstance(Key.get(rpcProviderOfInteger));
+
+    assertEquals((Integer)100, provider.get());
+    testModule.setNextIntToReturn(120);
+    assertEquals((Integer)100, provider.get());
+    testScope.beginNewScope();
+    assertEquals((Integer)120, provider.get());
+  }
+
+  public void testWithAnnotation() throws BindException, RemoteException {
+    TestModule testModule = new TestModule();
+    Injector injector = Guice.createInjector(testModule);
+    RpcProvider<Long> provider = injector
+        .getInstance(Key.get(rpcProviderOfLong, TestAnnotation.class));
+    assertEquals((Long)0xffL, provider.get());
+  }
+
+  public void testWithInjectedParameters() throws BindException, RemoteException {
+    TestModule testModule = new TestModule();
+    Injector injector = Guice.createInjector(testModule);
+    RpcProvider<Pair<Double, String>> provider = injector
+        .getInstance(Key.get(rpcProviderOfPair));
+    Pair<Double, String> pair = provider.get();
+    assertEquals(pair.first, 4.0d);
+  }
+
+  public void testWithThrownException() {
+    TestModule testModule = new TestModule();
+    Injector injector = Guice.createInjector(testModule);
+    RpcProvider<Float> provider = injector
+        .getInstance(Key.get(rpcProviderOfFloat));
+    try {
+      provider.get();
+      fail();
+    } catch (RemoteException e) {
+      fail();
+    } catch (BindException e) {
+      // good
+    }
+  }
+
+  public void testExposedMethod() throws BindException, RemoteException {
+    TestModule testModule = new TestModule();
+    Injector injector = Guice.createInjector(testModule);
+    RpcProvider<String> provider = injector
+        .getInstance(Key.get(rpcProviderOfString, Names.named("fruit")));
+    assertEquals("apple", provider.get());
+
+  }
+  
+  private static class Pair<A, B> {
+    A first;
+    B second;
+
+    Pair(A a, B b) {
+      this.first= a;
+      this.second = b;
+    }
+  }
+}
\ No newline at end of file
diff --git a/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java b/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java
new file mode 100644
index 0000000..1f4f977
--- /dev/null
+++ b/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java
@@ -0,0 +1,1552 @@
+/**
+ * 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 com.google.inject.throwingproviders;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.inject.AbstractModule;
+import com.google.inject.Asserts;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.OutOfScopeException;
+import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.Scope;
+import com.google.inject.ScopeAnnotation;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.util.Classes;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.Message;
+import com.google.inject.throwingproviders.ThrowingProviderBinder.Result;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.net.BindException;
+import java.rmi.AccessException;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.TooManyListenersException;
+
+/**
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ * @author sameb@google.com (Sam Berlin)
+ */
+public class CheckedProviderTest extends TestCase {
+  @Target(METHOD) @Retention(RUNTIME) @BindingAnnotation
+  @interface NotExceptionScoping { };
+  
+  private static final Function<Dependency<?>, Key<?>> DEPENDENCY_TO_KEY =
+      new Function<Dependency<?>, Key<?>>() {
+        public Key<?> apply(Dependency<?> from) {
+          return from.getKey();
+        }
+      };
+
+  private final TypeLiteral<RemoteProvider<Foo>> remoteProviderOfFoo
+      = new TypeLiteral<RemoteProvider<Foo>>() { };
+  private final MockRemoteProvider<Foo> mockRemoteProvider = new MockRemoteProvider<Foo>();
+  private final TestScope testScope = new TestScope();
+  
+  private Injector bindInjector;  
+  private Injector providesInjector;
+  private Injector cxtorInjector;
+  
+  @Override
+  protected void setUp() throws Exception {
+    MockFoo.nextToThrow = null;
+    MockFoo.nextToReturn = null;
+    AnotherMockFoo.nextToThrow = null;
+    AnotherMockFoo.nextToReturn = null;
+    
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .to(mockRemoteProvider)
+            .in(testScope);
+
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .annotatedWith(NotExceptionScoping.class)
+            .scopeExceptions(false)
+            .to(mockRemoteProvider)
+            .in(testScope);
+
+      }
+    });  
+    
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+       install(ThrowingProviderBinder.forModule(this));
+       bindScope(TestScope.Scoped.class, testScope);
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      @TestScope.Scoped
+      Foo throwOrGet() throws RemoteException, BindException {
+        return mockRemoteProvider.get();
+      }
+
+      @SuppressWarnings("unused")
+      @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false)
+      @NotExceptionScoping
+      @TestScope.Scoped
+      Foo notExceptionScopingThrowOrGet() throws RemoteException, BindException {
+        return mockRemoteProvider.get();
+      }    
+      
+    });
+    
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+          .bind(RemoteProvider.class, Foo.class)
+          .providing(MockFoo.class)
+          .in(testScope);
+
+        ThrowingProviderBinder.create(binder())
+          .bind(RemoteProvider.class, Foo.class)
+          .annotatedWith(NotExceptionScoping.class)
+          .scopeExceptions(false)
+          .providing(MockFoo.class)
+          .in(testScope);
+        
+      }
+    });
+  }
+
+  public void testExceptionsThrown_Bind() throws Exception {
+    tExceptionsThrown(bindInjector);
+  }
+  
+  public void testExceptionsThrown_Provides() throws Exception {
+    tExceptionsThrown(providesInjector);
+  }
+  
+  public void testExceptionsThrown_Cxtor() throws Exception {
+    tExceptionsThrown(cxtorInjector);
+  }
+  
+  private void tExceptionsThrown(Injector injector) throws Exception {
+    RemoteProvider<Foo> remoteProvider = 
+      injector.getInstance(Key.get(remoteProviderOfFoo));
+
+    mockRemoteProvider.throwOnNextGet(new BindException("kaboom!"));
+    MockFoo.nextToThrow = new BindException("kaboom!");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (BindException expected) {
+      assertEquals("kaboom!", expected.getMessage());
+    }
+  }
+
+  public void testValuesScoped_Bind() throws Exception  {
+    tValuesScoped(bindInjector, null);
+  }
+  
+  public void testValuesScoped_Provides() throws Exception  {
+    tValuesScoped(providesInjector, null);
+  }
+  
+  public void testValuesScopedWhenNotExceptionScoping_Bind() throws Exception  {
+    tValuesScoped(bindInjector, NotExceptionScoping.class);
+  }
+  
+  public void testValuesScopedWhenNotExceptionScoping_Provides() throws Exception  {
+    tValuesScoped(providesInjector, NotExceptionScoping.class);
+  }
+
+  private void tValuesScoped(Injector injector, 
+      Class<? extends Annotation> annotation) throws Exception {
+    Key<RemoteProvider<Foo>> key = annotation != null ? 
+        Key.get(remoteProviderOfFoo, annotation) :
+        Key.get(remoteProviderOfFoo);
+    RemoteProvider<Foo> remoteProvider = injector.getInstance(key);
+    
+    mockRemoteProvider.setNextToReturn(new SimpleFoo("A"));
+    assertEquals("A", remoteProvider.get().s());
+
+    mockRemoteProvider.setNextToReturn(new SimpleFoo("B"));
+    assertEquals("A", remoteProvider.get().s());
+
+    testScope.beginNewScope();
+    assertEquals("B", remoteProvider.get().s());
+  }
+  
+  public void testValuesScoped_Cxtor() throws Exception {
+    RemoteProvider<Foo> remoteProvider = 
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
+
+    Foo retrieved = remoteProvider.get();
+    assertSame(retrieved, remoteProvider.get()); // same, not in new scope.
+    
+    testScope.beginNewScope();
+    assertNotSame(retrieved, remoteProvider.get()); // different, new scope.
+  }
+
+  public void testExceptionsScoped_Bind() throws Exception {
+    tExceptionsScoped(bindInjector);
+  }
+  
+  public void testExceptionsScoped_Provides() throws Exception {
+    tExceptionsScoped(providesInjector);
+  }
+  
+  public void testExceptionScopes_Cxtor() throws Exception {
+    tExceptionsScoped(cxtorInjector);
+  }
+  
+  private void tExceptionsScoped(Injector injector) throws Exception {
+    RemoteProvider<Foo> remoteProvider = 
+        injector.getInstance(Key.get(remoteProviderOfFoo));
+
+    mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
+    MockFoo.nextToThrow = new RemoteException("A");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("A", expected.getMessage());
+    }
+    
+    mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
+    MockFoo.nextToThrow = new RemoteException("B");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("A", expected.getMessage());
+    }
+  }
+  
+  public void testExceptionsNotScopedWhenNotExceptionScoping_Bind() throws Exception {
+    tExceptionsNotScopedWhenNotExceptionScoping(bindInjector);
+  }
+  
+  public void testExceptionsNotScopedWhenNotExceptionScoping_Provides() throws Exception {
+    tExceptionsNotScopedWhenNotExceptionScoping(providesInjector);
+  }
+  
+  public void testExceptionNotScopedWhenNotExceptionScoping_Cxtor() throws Exception {
+    tExceptionsNotScopedWhenNotExceptionScoping(cxtorInjector);
+  }
+  
+  private void tExceptionsNotScopedWhenNotExceptionScoping(Injector injector) throws Exception {
+    RemoteProvider<Foo> remoteProvider = 
+        injector.getInstance(Key.get(remoteProviderOfFoo, NotExceptionScoping.class));
+
+    mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
+    MockFoo.nextToThrow = new RemoteException("A");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("A", expected.getMessage());
+    }
+    
+    mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
+    MockFoo.nextToThrow = new RemoteException("B");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("B", expected.getMessage());
+    }
+  }
+  
+  public void testAnnotations_Bind() throws Exception {
+    final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>();
+    final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .annotatedWith(Names.named("a"))
+            .to(mockRemoteProviderA);
+
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .to(mockRemoteProviderB);
+      }
+    });
+    tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB);
+  }
+  
+  public void testAnnotations_Provides() throws Exception {
+    final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>();
+    final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+       }
+       
+       @SuppressWarnings("unused")
+       @CheckedProvides(RemoteProvider.class)
+       @Named("a")
+       Foo throwOrGet() throws RemoteException, BindException {
+         return mockRemoteProviderA.get();
+       }
+       
+       @SuppressWarnings("unused")
+       @CheckedProvides(RemoteProvider.class)
+       Foo throwOrGet2() throws RemoteException, BindException {
+         return mockRemoteProviderB.get();
+       }
+    });
+    tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB);
+  }
+  
+  private void tAnnotations(Injector injector, MockRemoteProvider<Foo> mockA,
+      MockRemoteProvider<Foo> mockB) throws Exception {
+    mockA.setNextToReturn(new SimpleFoo("A"));
+    mockB.setNextToReturn(new SimpleFoo("B"));
+    assertEquals("A", 
+        injector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());
+
+    assertEquals("B", 
+        injector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
+  }
+  
+  public void testAnnotations_Cxtor() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .annotatedWith(Names.named("a"))
+            .providing(MockFoo.class);
+
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .providing(AnotherMockFoo.class);
+      }
+    });
+    MockFoo.nextToReturn = "A";
+    AnotherMockFoo.nextToReturn = "B";
+    assertEquals("A", 
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());
+
+    assertEquals("B", 
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
+  }
+  
+  public void testUndeclaredExceptions_Bind() throws Exception {
+    tUndeclaredExceptions(bindInjector);
+  }
+  
+  public void testUndeclaredExceptions_Provides() throws Exception {
+    tUndeclaredExceptions(providesInjector);
+  }
+  
+  public void testUndeclaredExceptions_Cxtor() throws Exception {
+    tUndeclaredExceptions(cxtorInjector);
+  }
+
+  private void tUndeclaredExceptions(Injector injector) throws Exception { 
+    RemoteProvider<Foo> remoteProvider = 
+        injector.getInstance(Key.get(remoteProviderOfFoo));
+    mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A"));
+    MockFoo.nextToThrow = new IndexOutOfBoundsException("A");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RuntimeException e) {
+      assertEquals("A", e.getCause().getMessage());
+    }
+
+    // undeclared exceptions shouldn't be scoped
+    mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("B"));
+    MockFoo.nextToThrow = new IndexOutOfBoundsException("B");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RuntimeException e) {
+      assertEquals("B", e.getCause().getMessage());
+    }
+  }
+
+  public void testThrowingProviderSubclassing() throws Exception {
+    final SubMockRemoteProvider aProvider = new SubMockRemoteProvider();
+    aProvider.setNextToReturn(new SimpleFoo("A"));
+
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .to(aProvider);
+      }
+    });
+
+    assertEquals("A",
+        bindInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
+  }
+
+  static class SubMockRemoteProvider extends MockRemoteProvider<Foo> { }
+
+  public void testBindingToNonInterfaceType_Bind() throws Exception {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(MockRemoteProvider.class, Foo.class)
+              .to(mockRemoteProvider);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testBindingToNonInterfaceType_Provides() throws Exception {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+          
+        @SuppressWarnings("unused")
+        @CheckedProvides(MockRemoteProvider.class)
+        Foo foo() {
+          return null;
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }  
+  
+  public void testBindingToSubSubInterface_Bind() throws Exception {
+    try {
+      bindInjector = Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(SubRemoteProvider.class, Foo.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testBindingToSubSubInterface_Provides() throws Exception {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+          
+        @SuppressWarnings("unused")
+        @CheckedProvides(SubRemoteProvider.class)
+        Foo foo() {
+          return null;
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }    
+
+  interface SubRemoteProvider extends RemoteProvider<String> { }
+
+  public void testBindingToInterfaceWithExtraMethod_Bind() throws Exception {
+    try {
+      bindInjector = Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProviderWithExtraMethod.class, Foo.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " 
+          + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testBindingToInterfaceWithExtraMethod_Provides() throws Exception {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+          
+        @SuppressWarnings("unused")
+        @CheckedProvides(RemoteProviderWithExtraMethod.class)
+        Foo foo() {
+          return null;
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " 
+          + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testDependencies_Bind() {
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("Foo");
+        bind(Integer.class).toInstance(5);
+        bind(Double.class).toInstance(5d);
+        bind(Long.class).toInstance(5L);
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .to(DependentRemoteProvider.class);
+      }
+    });
+    
+    HasDependencies hasDependencies =
+        (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfFoo));
+    hasDependencies = 
+        (HasDependencies)bindInjector.getBinding(
+            Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
+    // Make sure that that is dependent on DependentRemoteProvider.
+    assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)), 
+        Iterables.getOnlyElement(hasDependencies.getDependencies()));
+    // And make sure DependentRemoteProvider has the proper dependencies.
+    hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class);
+    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
+        Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
+    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
+        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
+  }
+  
+  public void testDependencies_Provides() {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("Foo");
+        bind(Integer.class).toInstance(5);
+        bind(Double.class).toInstance(5d);
+        bind(Long.class).toInstance(5L);
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      Foo foo(String s, Integer i, Double d, Long l) {
+        return null;
+      }
+    });
+    
+    HasDependencies hasDependencies =
+        (HasDependencies) providesInjector.getBinding(Key.get(remoteProviderOfFoo));
+    // RemoteProvider<String> is dependent on the provider method..
+    hasDependencies = (HasDependencies) providesInjector.getBinding(
+        Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
+    // And the provider method has our real dependencies..
+    hasDependencies = (HasDependencies)providesInjector.getBinding(
+        Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
+    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
+        Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
+    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
+        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
+  }  
+  
+  public void testDependencies_Cxtor() {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("Foo");
+        bind(Integer.class).toInstance(5);
+        bind(Double.class).toInstance(5d);
+        bind(Long.class).toInstance(5L);
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .providing(DependentMockFoo.class);
+      }
+    });
+    
+    Key<?> key = Key.get(remoteProviderOfFoo);
+    
+    // RemoteProvider<String> is dependent on Result.
+    HasDependencies hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
+    key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
+    assertEquals(Result.class, key.getTypeLiteral().getRawType());
+
+    // Result is dependent on the fake CheckedProvider impl
+    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
+    key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
+    assertTrue(CheckedProvider.class.isAssignableFrom(key.getTypeLiteral().getRawType()));
+    
+    // And the CheckedProvider is dependent on DependentMockFoo...
+    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
+    key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
+    assertEquals(DependentMockFoo.class, key.getTypeLiteral().getRawType());
+    
+    // And DependentMockFoo is dependent on the goods.
+    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key); 
+    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
+        Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
+    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
+        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
+  }  
+
+  interface RemoteProviderWithExtraMethod<T> extends CheckedProvider<T> {
+    T get(T defaultValue) throws RemoteException, BindException;
+  }
+
+  interface RemoteProvider<T> extends CheckedProvider<T> { 
+    public T get() throws RemoteException, BindException;
+  }
+  
+  static class DependentMockFoo implements Foo {
+    @Inject double foo;
+    
+    @ThrowingInject public DependentMockFoo(String foo, int bar) {
+    }
+    
+    @Inject void initialize(long foo) {}
+    
+    @Override
+    public String s() {
+      return null;
+    }
+  }
+  
+  static class DependentRemoteProvider<T> implements RemoteProvider<T> {
+    @Inject double foo;
+    
+    @Inject public DependentRemoteProvider(String foo, int bar) {
+    }
+    
+    @Inject void initialize(long foo) {}
+    
+    public T get() {
+      return null;
+    }
+  }
+  
+  interface Foo {
+    String s();
+  }
+  
+  static class SimpleFoo implements Foo {
+    private String s;
+    
+    SimpleFoo(String s) {
+      this.s = s;
+    }
+    
+    @Override
+    public String s() {
+      return s;
+    }
+    
+    @Override
+    public String toString() {
+      return s;
+    }
+  }
+  
+  static class MockFoo implements Foo {
+    static Exception nextToThrow;    
+    static String nextToReturn;
+    
+    @ThrowingInject
+    MockFoo() throws RemoteException, BindException {
+      if (nextToThrow instanceof RemoteException) {
+        throw (RemoteException) nextToThrow;
+      } else if (nextToThrow instanceof BindException) {
+        throw (BindException) nextToThrow;
+      } else if (nextToThrow instanceof RuntimeException) {
+        throw (RuntimeException) nextToThrow;
+      } else if (nextToThrow == null) {
+        // Do nothing, return this.
+      } else {
+        throw new AssertionError("nextToThrow must be a runtime or remote exception");
+      }
+    }
+    
+    @Override
+    public String s() {
+      return nextToReturn;
+    }
+    
+    @Override
+    public String toString() {
+      return nextToReturn;
+    }
+  }
+  
+  static class AnotherMockFoo implements Foo {
+    static Exception nextToThrow;    
+    static String nextToReturn;
+    
+    @ThrowingInject
+    AnotherMockFoo() throws RemoteException, BindException {
+      if (nextToThrow instanceof RemoteException) {
+        throw (RemoteException) nextToThrow;
+      } else if (nextToThrow instanceof BindException) {
+        throw (BindException) nextToThrow;
+      } else if (nextToThrow instanceof RuntimeException) {
+        throw (RuntimeException) nextToThrow;
+      } else if (nextToThrow == null) {
+        // Do nothing, return this.
+      } else {
+        throw new AssertionError("nextToThrow must be a runtime or remote exception");
+      }
+    }
+    
+    @Override
+    public String s() {
+      return nextToReturn;
+    }
+    
+    @Override
+    public String toString() {
+      return nextToReturn;
+    }
+  }
+  
+  static class MockRemoteProvider<T> implements RemoteProvider<T> {
+    Exception nextToThrow;
+    T nextToReturn;
+
+    public void throwOnNextGet(Exception nextToThrow) {
+      this.nextToThrow = nextToThrow;
+    }
+
+    public void setNextToReturn(T nextToReturn) {
+      this.nextToReturn = nextToReturn;
+    }
+    
+    public T get() throws RemoteException, BindException {
+      if (nextToThrow instanceof RemoteException) {
+        throw (RemoteException) nextToThrow;
+      } else if (nextToThrow instanceof BindException) {
+        throw (BindException) nextToThrow;
+      } else if (nextToThrow instanceof RuntimeException) {
+        throw (RuntimeException) nextToThrow;
+      } else if (nextToThrow == null) {
+        return nextToReturn;
+      } else {
+        throw new AssertionError("nextToThrow must be a runtime or remote exception");
+      }
+    }
+  }
+
+  public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException {
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(StringRemoteProvider.class, String.class)
+            .to(new StringRemoteProvider() {
+              public String get() {
+                return "A";
+              }
+            });
+      }
+    });
+    
+    assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get());
+  }
+  
+  public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(StringRemoteProvider.class)
+      String foo() throws RemoteException {
+          return "A";
+      }
+    });
+    
+    assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get());
+  }
+
+  interface StringRemoteProvider extends CheckedProvider<String> {
+    @Override String get() throws RemoteException;  
+  }
+
+  @SuppressWarnings("deprecation")
+  public void testBindingToInterfaceWithGeneric_Bind() throws Exception {
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, new TypeLiteral<List<String>>() { }.getType())
+            .to(new RemoteProvider<List<String>>() {
+              public List<String> get() {
+                return Arrays.asList("A", "B");
+              }
+            });
+      }
+    });
+
+    Key<RemoteProvider<List<String>>> key
+        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
+    assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
+  }
+  
+  public void testBindingToInterfaceWithGeneric_BindUsingTypeLiteral() throws Exception {
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
+            .to(new RemoteProvider<List<String>>() {
+              public List<String> get() {
+                return Arrays.asList("A", "B");
+              }
+            });
+      }
+    });
+
+    Key<RemoteProvider<List<String>>> key
+        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
+    assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
+  }
+  
+  public void testBindingToInterfaceWithGeneric_Provides() throws Exception {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      List<String> foo() throws RemoteException {
+          return Arrays.asList("A", "B");
+      }
+    });
+
+    Key<RemoteProvider<List<String>>> key
+        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
+    assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get());
+  }
+  
+  public void testBindingToInterfaceWithGeneric_Cxtor() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+        .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
+        .providing(new TypeLiteral<ThrowingArrayList<String>>() {});
+      }
+    });
+
+    Key<RemoteProvider<List<String>>> key
+        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
+    assertEquals(Arrays.asList(), cxtorInjector.getInstance(key).get());
+  }
+  
+  private static class ThrowingArrayList<T> extends ArrayList<T> {
+    @SuppressWarnings("unused")
+    @ThrowingInject
+    ThrowingArrayList() {}
+  }
+  
+  public void testProviderMethodWithWrongException() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(RemoteProvider.class)
+        String foo() throws InterruptedException {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(InterruptedException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")", 
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testCxtorWithWrongException() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(WrongExceptionFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(InterruptedException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")", 
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  static class WrongExceptionFoo implements Foo {
+    @SuppressWarnings("unused")
+    @ThrowingInject
+    public WrongExceptionFoo() throws InterruptedException {
+    }
+    
+    @Override
+    public String s() { return null; }
+  }
+  
+  public void testProviderMethodWithSubclassOfExceptionIsOk() throws Exception {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      Foo foo() throws AccessException {
+        throw new AccessException("boo!");
+      }
+    });
+    
+    RemoteProvider<Foo> remoteProvider = 
+      providesInjector.getInstance(Key.get(remoteProviderOfFoo));
+
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertTrue(expected instanceof AccessException);
+      assertEquals("boo!", expected.getMessage());
+    }
+  }
+  
+  public void testCxtorWithSubclassOfExceptionIsOk() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(SubclassExceptionFoo.class);
+        }
+      });
+    
+    RemoteProvider<Foo> remoteProvider = 
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
+
+      try {
+        remoteProvider.get();
+        fail();
+      } catch (RemoteException expected) {
+        assertTrue(expected instanceof AccessException);
+        assertEquals("boo!", expected.getMessage());
+      }
+  }
+  
+  static class SubclassExceptionFoo implements Foo {
+    @ThrowingInject
+    public SubclassExceptionFoo() throws AccessException {
+      throw new AccessException("boo!");
+    }
+    
+    @Override
+    public String s() { return null; }
+  }
+  
+  public void testProviderMethodWithSuperclassExceptionFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(RemoteProvider.class)
+        Foo foo() throws IOException {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(IOException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")", 
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testCxtorWithSuperclassExceptionFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(SuperclassExceptionFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(IOException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")", 
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  static class SuperclassExceptionFoo implements Foo {
+    @SuppressWarnings("unused")
+    @ThrowingInject
+    public SuperclassExceptionFoo() throws IOException {
+    }
+    
+    @Override
+    public String s() { return null; }
+  }
+  
+  public void testProviderMethodWithRuntimeExceptionsIsOk() throws Exception {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      Foo foo() throws RuntimeException {
+        throw new RuntimeException("boo!");
+      }
+    });
+    
+    RemoteProvider<Foo> remoteProvider = 
+      providesInjector.getInstance(Key.get(remoteProviderOfFoo));
+
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RuntimeException expected) {
+      assertEquals("boo!", expected.getCause().getMessage());
+    }
+  }
+  
+  public void testCxtorWithRuntimeExceptionsIsOk() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .providing(RuntimeExceptionFoo.class);
+      }
+    });
+    
+    RemoteProvider<Foo> remoteProvider = 
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
+
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RuntimeException expected) {
+      assertEquals("boo!", expected.getCause().getMessage());
+    }
+  }
+    
+  static class RuntimeExceptionFoo implements Foo {
+    @ThrowingInject
+    public RuntimeExceptionFoo() throws RuntimeException {
+      throw new RuntimeException("boo!");
+    }
+    
+    @Override
+    public String s() { return null; }
+  }
+  
+  private static class SubBindException extends BindException {}
+  
+  public void testProviderMethodWithManyExceptions() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(RemoteProvider.class)
+        String foo() throws InterruptedException, RuntimeException, RemoteException, 
+                            AccessException, TooManyListenersException,
+                            BindException, SubBindException {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
+      List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
+      assertEquals(InterruptedException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")", 
+          errors.get(0).getMessage());
+      assertEquals(TooManyListenersException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")", 
+          errors.get(1).getMessage());
+      assertEquals(2, errors.size());
+    }
+  }
+  
+  public void testCxtorWithManyExceptions() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(ManyExceptionFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
+      List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
+      assertEquals(InterruptedException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")", 
+          errors.get(0).getMessage());
+      assertEquals(TooManyListenersException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")", 
+          errors.get(1).getMessage());
+      assertEquals(2, errors.size());
+    }
+  }
+  
+  static class ManyExceptionFoo implements Foo {
+    @SuppressWarnings("unused")
+    @ThrowingInject
+    public ManyExceptionFoo()
+        throws InterruptedException,
+        RuntimeException,
+        RemoteException,
+        AccessException,
+        TooManyListenersException,
+        BindException,
+        SubBindException {
+    }
+    
+    @Override
+    public String s() { return null; }
+  }
+  
+  public void testMoreTypeParameters() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(TooManyTypeParameters.class)
+        String foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }    
+  }
+  
+  public void testWrongThrowingProviderType() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(WrongThrowingProviderType.class)
+        String foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(WrongThrowingProviderType.class.getName() 
+          + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider "
+          + "(java.lang.String) is not a generic type",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }    
+  }
+  
+  public void testOneMethodThatIsntGet() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(OneNoneGetMethod.class)
+        String foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(OneNoneGetMethod.class.getName() 
+          + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]),
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testManyMethods() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(ManyMethods.class)
+        String foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(ManyMethods.class.getName() 
+          + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()),
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testIncorrectPredefinedType_Bind() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(StringRemoteProvider.class, Integer.class)
+              .to(new StringRemoteProvider() {
+                public String get() {
+                  return "A";
+                }
+              });
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(StringRemoteProvider.class.getName() 
+          + " expects the value type to be java.lang.String, but it was java.lang.Integer",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testIncorrectPredefinedType_Provides() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(StringRemoteProvider.class)
+        Integer foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(StringRemoteProvider.class.getName() 
+          + " expects the value type to be java.lang.String, but it was java.lang.Integer",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  private static interface TooManyTypeParameters<T, P> extends CheckedProvider<T> {    
+  }
+  
+  private static interface WrongThrowingProviderType<T> extends CheckedProvider<String> {    
+  }
+  
+  private static interface OneNoneGetMethod<T> extends CheckedProvider<T> {
+    T bar();
+  }
+  
+  private static interface ManyMethods<T> extends CheckedProvider<T> {
+    T bar();
+    String baz();
+  }
+  
+  public void testResultSerializes() throws Exception {
+    Result result = Result.forValue("foo");
+    result = Asserts.reserialize(result);
+    assertEquals("foo", result.getOrThrow());
+  }
+  
+  public void testResultExceptionSerializes() throws Exception {
+    Result result = Result.forException(new Exception("boo"));
+    result = Asserts.reserialize(result);
+    try {
+      result.getOrThrow();
+      fail();
+    } catch(Exception ex) {
+      assertEquals("boo", ex.getMessage());
+    }
+  }
+  
+  public void testEarlyBindingError() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(StringRemoteProvider.class, String.class)
+              .to(FailingProvider.class);
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals("Could not find a suitable constructor in " + FailingProvider.class.getName()
+          + ". Classes must have either one (and only one) constructor annotated with @Inject"
+          + " or a zero-argument constructor that is not private.",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  private static class FailingProvider implements StringRemoteProvider {
+    // no @Inject.
+    @SuppressWarnings("unused")
+    FailingProvider(Integer foo) {}
+    
+    public String get() {
+      return null;
+    }
+  }
+  
+  public void testNoInjectionPointForUsing() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(InvalidFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals("Could not find a suitable constructor in " + InvalidFoo.class.getName()
+          + ". Classes must have either one (and only one) constructor annotated with "
+          + "@ThrowingInject.",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  static class InvalidFoo implements Foo {
+    public InvalidFoo(String dep) {
+    }
+    
+    @Override public String s() { return null; }
+  }
+  
+  public void testNoThrowingInject() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(NormalInjectableFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals("Could not find a suitable constructor in " + NormalInjectableFoo.class.getName()
+          + ". Classes must have either one (and only one) constructor annotated with "
+          + "@ThrowingInject.",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  static class NormalInjectableFoo implements Foo {
+    @Inject
+    public NormalInjectableFoo() {
+    }
+    
+    @Override public String s() { return null; }
+  }
+  
+  public void testProvisionExceptionOnDependenciesOfCxtor() throws Exception {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(ProvisionExceptionFoo.class);
+          bindScope(BadScope.class, new Scope() {
+            @Override
+            public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
+              return new Provider<T>() {
+                @Override
+                public T get() {
+                  throw new OutOfScopeException("failure");
+                }
+              };
+            }
+          });
+        }
+      });
+    
+    try {
+      injector.getInstance(Key.get(remoteProviderOfFoo)).get();
+      fail();
+    } catch(ProvisionException pe) {
+      assertEquals(2, pe.getErrorMessages().size());
+      List<Message> messages = Lists.newArrayList(pe.getErrorMessages());
+      assertEquals("Error in custom provider, com.google.inject.OutOfScopeException: failure",
+          messages.get(0).getMessage());
+      assertEquals("Error in custom provider, com.google.inject.OutOfScopeException: failure",
+          messages.get(1).getMessage());
+    }
+  }
+  
+  @ScopeAnnotation
+  @Target(ElementType.TYPE)
+  @Retention(RetentionPolicy.RUNTIME)
+  private @interface BadScope { }
+  
+  @BadScope private static class Unscoped1 {}
+  @BadScope private static class Unscoped2 {}
+  
+  static class ProvisionExceptionFoo implements Foo {
+    @ThrowingInject
+    public ProvisionExceptionFoo(Unscoped1 a, Unscoped2 b) {
+    }
+    
+    @Override public String s() { return null; }
+  }
+  
+  public void testUsingDoesntClashWithBindingsOfSameType() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(MockFoo.class);
+          bind(Foo.class).to(MockFoo.class);
+          bind(MockFoo.class).to(SubMockFoo.class);
+        }
+      });
+    
+    RemoteProvider<Foo> remoteProvider = 
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
+    Foo providerGot = remoteProvider.get();
+    Foo fooGot = cxtorInjector.getInstance(Foo.class);
+    Foo mockGot = cxtorInjector.getInstance(MockFoo.class);
+    
+    assertEquals(MockFoo.class, providerGot.getClass());
+    assertEquals(SubMockFoo.class, fooGot.getClass());
+    assertEquals(SubMockFoo.class, mockGot.getClass());
+  }
+  
+  static class SubMockFoo extends MockFoo {
+    public SubMockFoo() throws RemoteException, BindException {
+    }
+    
+  }
+}
diff --git a/extensions/throwingproviders/test/com/google/inject/throwingproviders/TestScope.java b/extensions/throwingproviders/test/com/google/inject/throwingproviders/TestScope.java
new file mode 100644
index 0000000..79445a6
--- /dev/null
+++ b/extensions/throwingproviders/test/com/google/inject/throwingproviders/TestScope.java
@@ -0,0 +1,60 @@
+/**
+ * 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 com.google.inject.throwingproviders;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.ScopeAnnotation;
+
+import java.lang.annotation.Retention;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A simple scope that can be explicitly reset.
+ *
+ * @author jmourits@google.com (Jerome Mourits)
+ */
+class TestScope implements Scope {
+
+  @Retention(RUNTIME) @ScopeAnnotation
+  public @interface Scoped { }
+
+  private Map<Key, Object> inScopeObjectsMap = new HashMap<Key, Object>();
+
+  public <T> Provider<T> scope(
+      final Key<T> key, final Provider<T> provider) {
+    return new Provider<T>() {
+      @SuppressWarnings({"unchecked"})
+      public T get() {
+        T t = (T) inScopeObjectsMap.get(key);
+        if (t == null) {
+          t = provider.get();
+          inScopeObjectsMap.put(key, t);
+        }
+        return t;
+      }
+    };
+  }
+
+  public void beginNewScope() {
+    inScopeObjectsMap = new HashMap<Key, Object>();
+  }
+}
diff --git a/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest.java b/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest.java
new file mode 100644
index 0000000..373c68d
--- /dev/null
+++ b/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest.java
@@ -0,0 +1,878 @@
+/**
+ * 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 com.google.inject.throwingproviders;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.inject.AbstractModule;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.internal.util.Classes;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.Message;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.rmi.AccessException;
+import java.rmi.RemoteException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.TooManyListenersException;
+
+/**
+ * @author jmourits@google.com (Jerome Mourits)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+@SuppressWarnings("deprecation")
+public class ThrowingProviderTest extends TestCase {
+  @Target(METHOD) @Retention(RUNTIME) @BindingAnnotation
+  @interface NotExceptionScoping { };
+
+  private final TypeLiteral<RemoteProvider<String>> remoteProviderOfString
+      = new TypeLiteral<RemoteProvider<String>>() { };
+  private final MockRemoteProvider<String> mockRemoteProvider = new MockRemoteProvider<String>();
+  private final TestScope testScope = new TestScope();
+  private Injector bindInjector = Guice.createInjector(new AbstractModule() {
+    protected void configure() {
+      ThrowingProviderBinder.create(binder())
+          .bind(RemoteProvider.class, String.class)
+          .to(mockRemoteProvider)
+          .in(testScope);
+      
+      ThrowingProviderBinder.create(binder())
+        .bind(RemoteProvider.class, String.class)
+        .annotatedWith(NotExceptionScoping.class)
+        .scopeExceptions(false)
+        .to(mockRemoteProvider)
+        .in(testScope);
+    }
+  });
+  private Injector providesInjector = Guice.createInjector(new AbstractModule() {
+    protected void configure() {
+      install(ThrowingProviderBinder.forModule(this));
+     bindScope(TestScope.Scoped.class, testScope);
+    }
+    
+    @SuppressWarnings("unused")
+    @CheckedProvides(RemoteProvider.class)
+    @TestScope.Scoped
+    String throwOrGet() throws RemoteException {
+      return mockRemoteProvider.get();
+    }
+    
+    @SuppressWarnings("unused")
+    @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false)
+    @NotExceptionScoping
+    @TestScope.Scoped
+    String notExceptionScopingThrowOrGet() throws RemoteException {
+      return mockRemoteProvider.get();
+    }    
+  });
+
+  public void testExceptionsThrown_Bind() {
+    tExceptionsThrown(bindInjector);
+  }
+  
+  public void testExceptionsThrown_Provides() {
+    tExceptionsThrown(providesInjector);
+  }
+  
+  private void tExceptionsThrown(Injector injector) {
+    RemoteProvider<String> remoteProvider = 
+      injector.getInstance(Key.get(remoteProviderOfString));
+
+    mockRemoteProvider.throwOnNextGet("kaboom!");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("kaboom!", expected.getMessage());
+    }
+  }
+
+  public void testValuesScoped_Bind() throws RemoteException {
+    tValuesScoped(bindInjector, null);
+  }
+  
+  public void testValuesScoped_Provides() throws RemoteException {
+    tValuesScoped(providesInjector, null);
+  }
+  
+  public void testValuesScopedWhenNotExceptionScoping_Bind() throws RemoteException {
+    tValuesScoped(bindInjector, NotExceptionScoping.class);
+  }
+  
+  public void testValuesScopedWhenNotExceptionScoping_Provides() throws RemoteException {
+    tValuesScoped(providesInjector, NotExceptionScoping.class);
+  }
+  
+  private void tValuesScoped(Injector injector, Class<? extends Annotation> annotation) 
+      throws RemoteException {
+    Key<RemoteProvider<String>> key = annotation != null ? 
+        Key.get(remoteProviderOfString, annotation) :
+        Key.get(remoteProviderOfString);
+    RemoteProvider<String> remoteProvider = injector.getInstance(key);
+
+    mockRemoteProvider.setNextToReturn("A");
+    assertEquals("A", remoteProvider.get());
+
+    mockRemoteProvider.setNextToReturn("B");
+    assertEquals("A", remoteProvider.get());
+
+    testScope.beginNewScope();
+    assertEquals("B", remoteProvider.get());
+  }
+
+  public void testExceptionsScoped_Bind() {
+    tExceptionsScoped(bindInjector);
+  }
+  
+  public void testExceptionsScoped_Provides() {
+    tExceptionsScoped(providesInjector);
+  }
+  
+  private void tExceptionsScoped(Injector injector) {
+    RemoteProvider<String> remoteProvider = 
+        injector.getInstance(Key.get(remoteProviderOfString));
+
+    mockRemoteProvider.throwOnNextGet("A");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("A", expected.getMessage());
+    }
+    
+    mockRemoteProvider.throwOnNextGet("B");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("A", expected.getMessage());
+    }
+  }
+
+  public void testExceptionsNotScopedWhenNotExceptionScoping_Bind() {
+    tExceptionsNotScopedWhenNotExceptionScoping(bindInjector);
+  }
+  
+  public void testExceptionsNotScopedWhenNotExceptionScoping_Provides() {
+    tExceptionsNotScopedWhenNotExceptionScoping(providesInjector);
+  }
+  
+  private void tExceptionsNotScopedWhenNotExceptionScoping(Injector injector) {
+    RemoteProvider<String> remoteProvider = 
+        injector.getInstance(Key.get(remoteProviderOfString, NotExceptionScoping.class));
+
+    mockRemoteProvider.throwOnNextGet("A");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("A", expected.getMessage());
+    }
+    
+    mockRemoteProvider.throwOnNextGet("B");
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertEquals("B", expected.getMessage());
+    }
+  }
+  
+  public void testAnnotations_Bind() throws RemoteException {
+    final MockRemoteProvider<String> mockRemoteProviderA = new MockRemoteProvider<String>();
+    final MockRemoteProvider<String> mockRemoteProviderB = new MockRemoteProvider<String>();
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, String.class)
+            .annotatedWith(Names.named("a"))
+            .to(mockRemoteProviderA);
+
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, String.class)
+            .to(mockRemoteProviderB);
+      }
+    });
+    tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB);
+  }
+  
+  public void testAnnotations_Provides() throws RemoteException {
+    final MockRemoteProvider<String> mockRemoteProviderA = new MockRemoteProvider<String>();
+    final MockRemoteProvider<String> mockRemoteProviderB = new MockRemoteProvider<String>();
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+       }
+       
+       @SuppressWarnings("unused")
+       @CheckedProvides(RemoteProvider.class)
+       @Named("a")
+       String throwOrGet() throws RemoteException {
+         return mockRemoteProviderA.get();
+       }
+       
+       @SuppressWarnings("unused")
+       @CheckedProvides(RemoteProvider.class)
+       String throwOrGet2() throws RemoteException {
+         return mockRemoteProviderB.get();
+       }
+    });
+    tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB);
+  }
+  
+  private void tAnnotations(Injector injector, MockRemoteProvider<String> mockA,
+      MockRemoteProvider<String> mockB) throws RemoteException {
+    mockA.setNextToReturn("A");
+    mockB.setNextToReturn("B");
+    assertEquals("A", 
+        injector.getInstance(Key.get(remoteProviderOfString, Names.named("a"))).get());
+
+    assertEquals("B", 
+        injector.getInstance(Key.get(remoteProviderOfString)).get());
+  }
+  
+  public void testUndeclaredExceptions_Bind() throws RemoteException {
+    tUndeclaredExceptions(bindInjector);
+  }
+  
+  public void testUndeclaredExceptions_Provides() throws RemoteException {
+    tUndeclaredExceptions(providesInjector);
+  }
+
+  private void tUndeclaredExceptions(Injector injector) throws RemoteException { 
+    RemoteProvider<String> remoteProvider = 
+        injector.getInstance(Key.get(remoteProviderOfString));
+    mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A"));
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RuntimeException e) {
+      assertEquals("A", e.getCause().getMessage());
+    }
+
+    // undeclared exceptions shouldn't be scoped
+    mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("B"));
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RuntimeException e) {
+      assertEquals("B", e.getCause().getMessage());
+    }
+  }
+
+  public void testThrowingProviderSubclassing() throws RemoteException {
+    final SubMockRemoteProvider aProvider = new SubMockRemoteProvider();
+    aProvider.setNextToReturn("A");
+
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, String.class)
+            .to(aProvider);
+      }
+    });
+
+    assertEquals("A",
+        bindInjector.getInstance(Key.get(remoteProviderOfString)).get());
+  }
+
+  static class SubMockRemoteProvider extends MockRemoteProvider<String> { }
+
+  public void testBindingToNonInterfaceType_Bind() throws RemoteException {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(MockRemoteProvider.class, String.class)
+              .to(mockRemoteProvider);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testBindingToNonInterfaceType_Provides() throws RemoteException {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+          
+        @SuppressWarnings("unused")
+        @CheckedProvides(MockRemoteProvider.class)
+        String foo() {
+          return null;
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }  
+  
+  public void testBindingToSubSubInterface_Bind() throws RemoteException {
+    try {
+      bindInjector = Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(SubRemoteProvider.class, String.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testBindingToSubSubInterface_Provides() throws RemoteException {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+          
+        @SuppressWarnings("unused")
+        @CheckedProvides(SubRemoteProvider.class)
+        String foo() {
+          return null;
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }    
+
+  interface SubRemoteProvider extends RemoteProvider<String> { }
+
+  public void testBindingToInterfaceWithExtraMethod_Bind() throws RemoteException {
+    try {
+      bindInjector = Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProviderWithExtraMethod.class, String.class);
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " 
+          + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testBindingToInterfaceWithExtraMethod_Provides() throws RemoteException {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+          
+        @SuppressWarnings("unused")
+        @CheckedProvides(RemoteProviderWithExtraMethod.class)
+        String foo() {
+          return null;
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " 
+          + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
+          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testDependencies_Bind() {
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toInstance("Foo");
+        bind(Integer.class).toInstance(5);
+        bind(Double.class).toInstance(5d);
+        bind(Long.class).toInstance(5L);
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, String.class)
+            .to(DependentRemoteProvider.class);
+      }
+    });
+    
+    HasDependencies hasDependencies =
+        (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfString));
+    hasDependencies = 
+        (HasDependencies)bindInjector.getBinding(
+            Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
+    // Make sure that that is dependent on DependentRemoteProvider.
+    assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)), 
+        Iterables.getOnlyElement(hasDependencies.getDependencies()));
+    // And make sure DependentRemoteProvider has the proper dependencies.
+    hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class);
+    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
+        Iterables.transform(hasDependencies.getDependencies(),
+          new Function<Dependency<?>, Key<?>>() {
+            public Key<?> apply(Dependency<?> from) {
+              return from.getKey();
+            }
+          }));
+    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
+        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
+  }
+  
+  public void testDependencies_Provides() {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(String.class).toInstance("Foo");
+        bind(Integer.class).toInstance(5);
+        bind(Double.class).toInstance(5d);
+        bind(Long.class).toInstance(5L);
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      String foo(String s, Integer i, Double d, Long l) {
+        return null;
+      }
+    });
+    
+    HasDependencies hasDependencies =
+        (HasDependencies)providesInjector.getBinding(Key.get(remoteProviderOfString));
+    // RemoteProvider<String> is dependent on the provider method..
+    hasDependencies = 
+        (HasDependencies)providesInjector.getBinding(
+            Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
+    // And the provider method has our real dependencies..
+    hasDependencies = (HasDependencies)providesInjector.getBinding(
+        Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
+    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
+        Iterables.transform(hasDependencies.getDependencies(),
+          new Function<Dependency<?>, Key<?>>() {
+            public Key<?> apply(Dependency<?> from) {
+              return from.getKey();
+            }
+          }));
+    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
+        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
+  }  
+
+  interface RemoteProviderWithExtraMethod<T> extends ThrowingProvider<T, RemoteException> {
+    T get(T defaultValue) throws RemoteException;
+  }
+
+  interface RemoteProvider<T> extends ThrowingProvider<T, RemoteException> { }
+  
+  static class DependentRemoteProvider<T> implements RemoteProvider<T> {
+    @Inject double foo;
+    
+    @Inject public DependentRemoteProvider(String foo, int bar) {
+    }
+    
+    @Inject void initialize(long foo) {}
+    
+    public T get() throws RemoteException {
+      return null;
+    }
+  }
+  
+  static class MockRemoteProvider<T> implements RemoteProvider<T> {
+    Exception nextToThrow;
+    T nextToReturn;
+    
+    public void throwOnNextGet(String message) {
+      throwOnNextGet(new RemoteException(message));
+    }
+
+    public void throwOnNextGet(Exception nextToThrow) {
+      this.nextToThrow = nextToThrow;
+    }
+
+    public void setNextToReturn(T nextToReturn) {
+      this.nextToReturn = nextToReturn;
+    }
+    
+    public T get() throws RemoteException {
+      if (nextToThrow instanceof RemoteException) {
+        throw (RemoteException) nextToThrow;
+      } else if (nextToThrow instanceof RuntimeException) {
+        throw (RuntimeException) nextToThrow;
+      } else if (nextToThrow == null) {
+        return nextToReturn;
+      } else {
+        throw new AssertionError("nextToThrow must be a runtime or remote exception");
+      }
+    }
+  }
+
+  public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException {
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(StringRemoteProvider.class, String.class)
+            .to(new StringRemoteProvider() {
+              public String get() throws RemoteException {
+                return "A";
+              }
+            });
+      }
+    });
+    
+    assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get());
+  }
+  
+  public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(StringRemoteProvider.class)
+      String foo() throws RemoteException {
+          return "A";
+      }
+    });
+    
+    assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get());
+  }
+
+  interface StringRemoteProvider extends ThrowingProvider<String, RemoteException> { }
+
+  public void testBindingToInterfaceWithGeneric_Bind() throws RemoteException {
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, new TypeLiteral<List<String>>() { }.getType())
+            .to(new RemoteProvider<List<String>>() {
+              public List<String> get() throws RemoteException {
+                return Arrays.asList("A", "B");
+              }
+            });
+      }
+    });
+
+    Key<RemoteProvider<List<String>>> key
+        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
+    assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
+  }
+  
+  public void testBindingToInterfaceWithGeneric_Provides() throws RemoteException {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      List<String> foo() throws RemoteException {
+          return Arrays.asList("A", "B");
+      }
+    });
+
+    Key<RemoteProvider<List<String>>> key
+        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
+    assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get());
+  }
+  
+  public void testProviderMethodWithWrongException() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(RemoteProvider.class)
+        String foo() throws InterruptedException {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(InterruptedException.class.getName() + " is not compatible with the exceptions (["
+          + RemoteException.class + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName() + ")",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testProviderMethodWithSubclassOfExceptionIsOk() {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      String foo() throws AccessException {
+        throw new AccessException("boo!");
+      }
+    });
+    
+    RemoteProvider<String> remoteProvider = 
+      providesInjector.getInstance(Key.get(remoteProviderOfString));
+
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RemoteException expected) {
+      assertTrue(expected instanceof AccessException);
+      assertEquals("boo!", expected.getMessage());
+    }
+  }
+  
+  public void testProviderMethodWithSuperclassFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(RemoteProvider.class)
+        String foo() throws IOException {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(IOException.class.getName() + " is not compatible with the exceptions (["
+          + RemoteException.class + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName() + ")",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testProviderMethodWithRuntimeExceptionsIsOk() throws RemoteException {
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        install(ThrowingProviderBinder.forModule(this));
+      }
+      
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      String foo() throws RuntimeException {
+        throw new RuntimeException("boo!");
+      }
+    });
+    
+    RemoteProvider<String> remoteProvider = 
+      providesInjector.getInstance(Key.get(remoteProviderOfString));
+
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RuntimeException expected) {
+      assertEquals("boo!", expected.getCause().getMessage());
+    }
+  }
+  
+  public void testProviderMethodWithManyExceptions() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(RemoteProvider.class)
+        String foo() throws InterruptedException, RuntimeException, RemoteException, 
+                            AccessException, TooManyListenersException {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
+      List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
+      assertEquals(InterruptedException.class.getName() + " is not compatible with the exceptions (["
+          + RemoteException.class + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName() + ")",
+          errors.get(0).getMessage());
+      assertEquals(TooManyListenersException.class.getName() + " is not compatible with the exceptions (["
+          + RemoteException.class + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName() + ")",
+          errors.get(1).getMessage());
+      assertEquals(2, errors.size());
+    }
+  }
+  
+  public void testMoreTypeParameters() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(TooManyTypeParameters.class)
+        String foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }    
+  }
+  
+  public void testWrongThrowingProviderType() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(WrongThrowingProviderType.class)
+        String foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(WrongThrowingProviderType.class.getName() 
+          + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider "
+          + "(java.lang.String) is not a generic type",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }    
+  }
+  
+  public void testOneMethodThatIsntGet() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(OneNoneGetMethod.class)
+        String foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(OneNoneGetMethod.class.getName() 
+          + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]),
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testManyMethods() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(ManyMethods.class)
+        String foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(ManyMethods.class.getName() 
+          + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()),
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testIncorrectPredefinedType_Bind() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(StringRemoteProvider.class, Integer.class)
+              .to(new StringRemoteProvider() {
+                public String get() throws RemoteException {
+                  return "A";
+                }
+              });
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(StringRemoteProvider.class.getName() 
+          + " expects the value type to be java.lang.String, but it was java.lang.Integer",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  public void testIncorrectPredefinedType_Provides() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          install(ThrowingProviderBinder.forModule(this));
+        }
+        
+        @SuppressWarnings("unused")
+        @CheckedProvides(StringRemoteProvider.class)
+        Integer foo() {
+            return null;
+        }
+      });
+      fail();
+    } catch(CreationException ce) {
+      assertEquals(StringRemoteProvider.class.getName() 
+          + " expects the value type to be java.lang.String, but it was java.lang.Integer",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+  
+  private static interface TooManyTypeParameters<T, P> extends ThrowingProvider<T, Exception> {    
+  }
+  
+  private static interface WrongThrowingProviderType<T> extends ThrowingProvider<String, Exception> {    
+  }
+  
+  private static interface OneNoneGetMethod<T> extends ThrowingProvider<T, Exception> {
+    T bar();
+  }
+  
+  private static interface ManyMethods<T> extends ThrowingProvider<T, Exception> {
+    T bar();
+    String baz();
+  }
+}
diff --git a/jdk8-tests/pom.xml b/jdk8-tests/pom.xml
new file mode 100644
index 0000000..7e04d21
--- /dev/null
+++ b/jdk8-tests/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Copyright (c) 2014 Google, Inc. All rights reserved.
+
+This program is licensed to you under the Apache License Version 2.0,
+and you may not use this file except in compliance with the Apache License Version 2.0.
+You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the Apache License Version 2.0 is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>guice-parent</artifactId>
+    <groupId>com.google.inject</groupId>
+    <version>4.0</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>jdk8-tests</artifactId>
+
+  <name>Google Guice - JDK8 Tests</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.inject</groupId>
+      <artifactId>guice</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava-testlib</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>8</source>
+          <target>8</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <!--
+          Override guice-parent's maven-jar-plugin settings to use the default instead.
+          Since there are no non-test sources for this module and we aren't generating
+          a manifest file for it, there's no MANIFEST.MF file where the parent configuration
+          is expecting it.
+          -->
+        <configuration combine.self="override" />
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java b/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java
new file mode 100644
index 0000000..29e0681
--- /dev/null
+++ b/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java
@@ -0,0 +1,223 @@
+/**
+ * Copyright (C) 2014 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.inject.jdk8;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.matcher.Matchers;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests for interception of default methods.
+ *
+ * @author cgdecker@google.com (Colin Decker)
+ */
+public class DefaultMethodInterceptionTest extends TestCase {
+
+  private static final AtomicInteger callCount = new AtomicInteger(0);
+  private static final AtomicInteger interceptedCallCount = new AtomicInteger(0);
+
+  // the interceptor's a lambda too
+  private final MethodInterceptor interceptor = invocation -> {
+    interceptedCallCount.incrementAndGet();
+    return invocation.proceed();
+  };
+
+  @Override
+  protected void setUp() throws Exception {
+    callCount.set(0);
+    interceptedCallCount.set(0);
+  }
+
+  @Retention(RUNTIME)
+  @Target({METHOD, TYPE})
+  public @interface InterceptMe {}
+
+  /** Interface with a default method annotated to be intercepted. */
+  public interface Foo {
+    @InterceptMe
+    default String defaultMethod() {
+      callCount.incrementAndGet();
+      return "Foo";
+    }
+  }
+
+  /** Foo implementation that does not override the default method. */
+  public static class NonOverridingFoo implements Foo {
+    public String methodCallingDefault() {
+      return "NonOverriding-" + defaultMethod();
+    }
+  }
+
+  public void testInterceptedDefaultMethod() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
+            interceptor);
+        bind(Foo.class).to(NonOverridingFoo.class);
+      }
+    });
+
+    Foo foo = injector.getInstance(Foo.class);
+    assertEquals("Foo", foo.defaultMethod());
+    assertEquals(1, callCount.get());
+    assertEquals(1, interceptedCallCount.get());
+  }
+
+  public void testInterceptedDefaultMethod_calledByAnotherMethod() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
+            interceptor);
+      }
+    });
+
+    NonOverridingFoo foo = injector.getInstance(NonOverridingFoo.class);
+    assertEquals("NonOverriding-Foo", foo.methodCallingDefault());
+    assertEquals(1, callCount.get());
+    assertEquals(1, interceptedCallCount.get());
+  }
+
+  /** A base class defining a method with the same signature as Foo's default method. */
+  public static class BaseClass {
+    // the definition of this method on the class will win over the default method
+    public String defaultMethod() {
+      callCount.incrementAndGet();
+      return "BaseClass";
+    }
+  }
+
+  /** Foo implementation that should use superclass method rather than default method. */
+  public static class InheritingFoo extends BaseClass implements Foo {
+  }
+
+  public void testInterceptedDefaultMethod_whenParentClassDefinesNonInterceptedMethod() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
+            interceptor);
+        bind(Foo.class).to(InheritingFoo.class);
+      }
+    });
+
+    // the concrete implementation that wins is not annotated
+    Foo foo = injector.getInstance(Foo.class);
+    assertEquals("BaseClass", foo.defaultMethod());
+    assertEquals(1, callCount.get());
+    assertEquals(0, interceptedCallCount.get());
+  }
+
+  /**
+   * A base class defining an intercepted method with the same signature as Foo's default method.
+   */
+  public static class BaseClass2 {
+    // the definition of this method on the class will win over the default method
+    @InterceptMe
+    public String defaultMethod() {
+      callCount.incrementAndGet();
+      return "BaseClass2";
+    }
+  }
+
+  /**
+   * Foo implementation that should use intercepted superclass method rather than default method.
+   */
+  public static class InheritingFoo2 extends BaseClass2 implements Foo {
+  }
+
+  public void testInterceptedDefaultMethod_whenParentClassDefinesInterceptedMethod() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
+            interceptor);
+        bind(Foo.class).to(InheritingFoo2.class);
+      }
+    });
+
+    // the concrete implementation that wins is not annotated
+    Foo foo = injector.getInstance(Foo.class);
+    assertEquals("BaseClass2", foo.defaultMethod());
+    assertEquals(1, callCount.get());
+    assertEquals(1, interceptedCallCount.get());
+  }
+
+  public interface Baz {
+    default String doSomething() {
+      return "Baz";
+    }
+
+    String doSomethingElse();
+  }
+
+  public static class BazImpl implements Baz {
+
+    @Override
+    public String doSomethingElse() {
+      return "BazImpl";
+    }
+  }
+
+  public void testInterception_ofAllMethodsOnType() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindInterceptor(Matchers.subclassesOf(Baz.class), Matchers.any(), interceptor);
+        bind(Baz.class).to(BazImpl.class);
+      }
+    });
+
+    Baz baz = injector.getInstance(Baz.class);
+
+    assertEquals("Baz", baz.doSomething());
+    assertEquals("BazImpl", baz.doSomethingElse());
+
+    assertEquals(2, interceptedCallCount.get());
+  }
+
+  public void testInterception_ofAllMethodsOnType_interceptsInheritedDefaultMethod() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindInterceptor(Matchers.subclassesOf(BazImpl.class), Matchers.any(), interceptor);
+        bind(Baz.class).to(BazImpl.class);
+      }
+    });
+
+    Baz baz = injector.getInstance(Baz.class);
+
+    assertEquals("Baz", baz.doSomething());
+    assertEquals("BazImpl", baz.doSomethingElse());
+
+    assertEquals(2, interceptedCallCount.get());
+  }
+}
diff --git a/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java b/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java
new file mode 100644
index 0000000..39a7498
--- /dev/null
+++ b/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright (C) 2014 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.inject.jdk8;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+import com.google.inject.TypeLiteral;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
+
+/**
+ * Test bindings to lambdas, method references, etc.
+ *
+ * @author cgdecker@google.com (Colin Decker)
+ */
+public class Java8LanguageFeatureBindingTest extends TestCase {
+
+  // Some of these tests are kind of weird.
+  // See https://github.com/google/guice/issues/757 for more on why they exist.
+
+  public void testBinding_lambdaToInterface() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(new TypeLiteral<Predicate<Object>>() {}).toInstance(o -> o != null);
+      }
+    });
+
+    Predicate<Object> predicate = injector.getInstance(new Key<Predicate<Object>>() {});
+    assertTrue(predicate.test(new Object()));
+    assertFalse(predicate.test(null));
+  }
+
+  public void testProviderMethod_returningLambda() throws Exception {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {}
+
+      @Provides
+      public Callable<String> provideCallable() {
+        return () -> "foo";
+      }
+    });
+
+    Callable<String> callable = injector.getInstance(new Key<Callable<String>>() {});
+    assertEquals("foo", callable.call());
+  }
+
+  public void testProviderMethod_containingLambda_throwingException() throws Exception {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {}
+
+      @Provides
+      public Callable<String> provideCallable() {
+        if (Boolean.parseBoolean("false")) { // avoid dead code warnings
+          return () -> "foo";
+        } else {
+          throw new RuntimeException("foo");
+        }
+      }
+    });
+
+    try {
+      injector.getInstance(new Key<Callable<String>>() {});
+    } catch (ProvisionException expected) {
+      assertTrue(expected.getCause() instanceof RuntimeException);
+      assertEquals("foo", expected.getCause().getMessage());
+    }
+  }
+
+  public void testProvider_usingJdk8Features() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          bind(String.class).toProvider(StringProvider.class);
+        }
+      });
+
+      fail();
+    } catch (CreationException expected) {
+    }
+
+    UUID uuid = UUID.randomUUID();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(UUID.class).toInstance(uuid);
+        bind(String.class).toProvider(StringProvider.class);
+      }
+    });
+
+    assertEquals(uuid.toString(), injector.getInstance(String.class));
+  }
+
+  private static final class StringProvider implements Provider<String> {
+    private final UUID uuid;
+
+    @Inject
+    StringProvider(UUID uuid) {
+      this.uuid = uuid;
+    }
+
+    @Override
+    public String get() {
+      return Collections.singleton(uuid).stream()
+          .map(UUID::toString)
+          .findFirst().get();
+    }
+  }
+
+  public void testBinding_toProvider_lambda() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        AtomicInteger i = new AtomicInteger();
+        bind(String.class).toProvider(() -> "Hello" + i.incrementAndGet());
+      }
+    });
+
+    assertEquals("Hello1", injector.getInstance(String.class));
+    assertEquals("Hello2", injector.getInstance(String.class));
+  }
+
+  public void testBinding_toProvider_methodReference() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toProvider(Java8LanguageFeatureBindingTest.this::provideString);
+      }
+    });
+
+    Provider<String> provider = injector.getProvider(String.class);
+    assertEquals("Hello", provider.get());
+  }
+
+  private String provideString() {
+    return "Hello";
+  }
+}
diff --git a/latest-api-diffs/1.0.xml b/latest-api-diffs/1.0.xml
new file mode 100644
index 0000000..5874586
--- /dev/null
+++ b/latest-api-diffs/1.0.xml
@@ -0,0 +1,2095 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<!-- on Tue May 19 17:01:51 PDT 2009 -->
+
+<api
+  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+  xsi:noNamespaceSchemaLocation='api.xsd'
+  name="1.0"
+  jdversion="1.1.1">
+
+<!--  Command line arguments =  -doclet jdiff.JDiff -docletpath /Applications/bin/jdiff-1.1.1/jdiff.jar:/Applications/bin/jdiff-1.1.1/xerces.jar -d /Users/jessewilson/Guice/guice-everything/api-diffs -classpath /usr/share/ant/lib/ant-launcher.jar:/usr/share/ant/lib/ant-jai.jar:/usr/share/ant/lib/ant-jmf.jar:/usr/share/ant/lib/ant-junit.jar:/usr/share/ant/lib/ant-nodeps.jar:/usr/share/ant/lib/ant-swing.jar:/usr/share/ant/lib/ant-testutil.jar:/usr/share/ant/lib/ant-trax.jar:/usr/share/ant/lib/ant.jar:/usr/share/ant/lib/junit.jar:/usr/share/ant/lib/xercesImpl.jar:/usr/share/ant/lib/xml-apis.jar -sourcepath /Users/jessewilson/Guice/guice-everything/tags/1.0/src:/Users/jessewilson/Guice/guice-everything/tags/1.0/servlet/src:/Users/jessewilson/Guice/guice-everything/tags/1.0/spring/src:/Users/jessewilson/Guice/guice-everything/tags/1.0/struts2/plugin/src -apiname 1.0 -baseURI http://www.w3.org -apidir /Users/jessewilson/Guice/guice-everything/api-diffs -source 1.5 -->
+<package name="com.google.inject">
+  <!-- start class com.google.inject.AbstractModule -->
+  <class name="AbstractModule" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Module"/>
+    <constructor name="AbstractModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="true"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="builder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="configure"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Configures a {@link Binder} via the exposed methods.]]>
+      </doc>
+    </method>
+    <method name="binder" return="com.google.inject.Binder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets direct access to the underlying {@code Binder}.]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[@see Binder#bindScope(Class, Scope)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Key)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Class)]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#bindConstant()]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[@see Binder#install(Module)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[@see Binder#addError(String, Object[])]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Throwable)]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[@see Binder#requestStaticInjection(Class[])]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindInterceptor(com.google.inject.matcher.Matcher,
+  com.google.inject.matcher.Matcher,
+  org.aopalliance.intercept.MethodInterceptor[])]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A support class for {@link Module}s which reduces repetition and results in
+ a more readable configuration. Simply extend this class, implement {@link
+ #configure()}, and call the inherited methods which mirror those found in
+ {@link Binder}. For example:
+
+ <pre>
+ import static com.google.inject.Names.named;
+
+ public class MyModule extends AbstractModule {
+   protected void configure() {
+     bind(Foo.class).to(FooImpl.class).in(Scopes.SINGLETON);
+     bind(BarImpl.class);
+     link(Bar.class).to(BarImpl.class);
+     bindConstant(named("port")).to(8080);
+   }
+ }
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.AbstractModule -->
+  <!-- start interface com.google.inject.Binder -->
+  <interface name="Binder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[Binds a method interceptor to methods matched by class and method
+ matchers.
+
+ @param classMatcher matches classes the interceptor should apply to. For
+     example: {@code only(Runnable.class)}.
+ @param methodMatcher matches methods the interceptor should apply to. For
+     example: {@code annotatedWith(Transactional.class)}.
+ @param interceptors to bind]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[Binds a scope to an annotation.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Creates a binding to a key.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Creates a binding to a type.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Creates a binding to a type.]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Binds a constant value to an annotation.]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject static fields
+ and methods in the given classes.
+
+ @param types for which static members will be injected]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[Uses the given module to configure more bindings.]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the current stage.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[Records an error message which will be presented to the user at a later
+ time. Unlike throwing an exception, this enable us to continue
+ configuring the Injector and discover more errors. Uses {@link
+ String#format(String, Object[])} to insert the arguments into the
+ message.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[Records an exception, the full details of which will be logged, and the
+ message of which will be presented to the user at a later
+ time. If your Module calls something that you worry may fail, you should
+ catch the exception and pass it into this.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Collects configuration information (primarily <i>bindings</i>) which will be
+ used to create an {@link Injector}. Guice provides this object to your
+ application's {@link Module}s so they may each contribute
+ their own bindings.
+
+ <p>The bindings contributed by {@code Module}s define how the {@code
+ Injector} resolves dependencies. A {@link Key} consisting of a type
+ and optional annotation uniquely identifies a binding within an {@code
+ Injector}.
+
+ <p>You may bind from a key to:
+
+ <ul>
+ <li>Another binding, which this binding's key is now "aliased to"
+ <li>Another binding, which references a {@link Provider} for this key
+ <li>A preconstructed instance
+ <li>A preconstructed instance which should be used as the {@link Provider}
+   for this binding
+ </ul>
+
+ <p>In addition, a binding may have an associated scope, such as
+ {@link Scopes#SINGLETON}, and singleton bindings may specify eager or lazy
+ initialization.
+
+ <p>See the users' guide appendix, "How the Injector resolves injection
+ requests," to better understand binding resolution.
+
+ <p>After an {@code Injector} has been created, its bindings may be
+ examined using methods like {@link Injector#getBinding(Key)}, but this
+ read-only {@link Binding} type is not used when <i>creating</i> the
+ bindings.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Binder -->
+  <!-- start interface com.google.inject.Binding -->
+  <interface name="Binding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for this binding.]]>
+      </doc>
+    </method>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns an arbitrary object containing information about the "place"
+ where this binding was configured. Used by Guice in the production of
+ descriptive error messages.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the provider guice uses to fulfill requests for this binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A mapping from a key (type and optional annotation) to a provider of
+ instances of that type.  This interface is part of the {@link Injector}
+ introspection API and is intended primary for use by tools.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Binding -->
+  <!-- start class com.google.inject.BindingAnnotation -->
+  <class name="BindingAnnotation"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates annotations which are used for binding. Only one such annotation
+ may apply to a single injection point. You must also annotate binder
+ annotations with {@code @Retention(RUNTIME)}. For example:
+
+ <pre>
+   {@code @}Retention(RUNTIME)
+   {@code @}Target({ FIELD, PARAMETER })
+   {@code @}BindingAnnotation
+   public {@code @}interface Transactional {}
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.BindingAnnotation -->
+  <!-- start class com.google.inject.CreationException -->
+  <class name="CreationException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="CreationException" type="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new exception for the given errors.]]>
+      </doc>
+    </constructor>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the error messages which resulted in this exception.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Thrown when errors occur while creating a {@link Injector}. Includes a list
+ of encountered errors. Typically, a client should catch this exception, log
+ it, and stop execution.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.CreationException -->
+  <!-- start class com.google.inject.Guice -->
+  <class name="Guice" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules.
+
+ @throws CreationException from which you can retrieve the individual error
+  messages]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules.
+
+ @throws CreationException from which you can retrieve the individual error
+  messages]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules, in a given development
+ stage.
+
+ @throws CreationException from which you can retrieve the individual error
+  messages.]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="java.lang.Iterable&lt;com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules, in a given development
+ stage.
+
+ @throws CreationException from which you can retrieve the individual error
+  messages.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[The entry point to the Guice framework. Creates {@link Injector}s from
+ {@link Module}s.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Guice -->
+  <!-- start class com.google.inject.ImplementedBy -->
+  <class name="ImplementedBy"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A pointer to the default implementation of a type.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ImplementedBy -->
+  <!-- start class com.google.inject.Inject -->
+  <class name="Inject"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates members of your implementation class (constructors, methods
+ and fields) into which the {@link Injector} should inject values.
+ The Injector fulfills injection requests for:
+
+ <ul>
+ <li>Every instance it constructs. The class being constructed must have
+ exactly one of its constructors marked with {@code @Inject} or must have a
+ constructor taking no parameters. The Injector then proceeds to perform
+ method and field injections.
+ 
+ <li>Pre-constructed instances passed to {@link Injector#injectMembers},
+ {@link com.google.inject.binder.LinkedBindingBuilder#toInstance(Object)} and
+ {@link com.google.inject.binder.LinkedBindingBuilder#toProvider(Provider)}.
+ In this case all constructors are, of course, ignored.
+
+ <li>Static fields and methods of classes which any {@link Module} has
+ specifically requested static injection for, using
+ {@link Binder#requestStaticInjection}.
+ </ul>
+
+ In all cases, a member can be injected regardless of its Java access
+ specifier (private, default, protected, public).
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Inject -->
+  <!-- start interface com.google.inject.Injector -->
+  <interface name="Injector"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="injectMembers"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Injects dependencies into the fields and methods of an existing object.
+ Does not inject the constructor.]]>
+      </doc>
+    </method>
+    <method name="getBindings" return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets all explicit bindings.]]>
+      </doc>
+    </method>
+    <method name="getBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a binding for the given key.]]>
+      </doc>
+    </method>
+    <method name="findBindingsByType" return="java.util.List&lt;com.google.inject.Binding&lt;T&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Finds all bindings to the given type.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets the provider bound to the given key.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets the provider bound to the given type.]]>
+      </doc>
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets an instance bound to the given key; equivalent to
+ {@code getProvider(key).get()}.]]>
+      </doc>
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets an instance bound to the given type; equivalent to
+ {@code getProvider(type).get()}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Fulfills requests for the object instances that make up your application,
+ always ensuring that these instances are properly injected before they are
+ returned. The {@code Injector} is the heart of the Guice framework,
+ although you don't typically interact with it directly very often. This
+ "behind-the-scenes" operation is what distinguishes the dependency
+ injection pattern from its cousin, service locator.
+
+ <p>The {@code Injector} API has a few additional features: it allows
+ pre-constructed instances to have their fields and methods injected and
+ offers programmatic introspection to support tool development.
+
+ <p>Contains several default bindings:
+
+ <ul>
+ <li>This {@link Injector} instance itself
+ <li>A {@code Provider<T>} for each binding of type {@code T}
+ <li>The {@link java.util.logging.Logger} for the class being injected
+ <li>The {@link Stage} in which the Injector was created
+ </ul>
+
+ Injectors are created using the facade class {@link Guice}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Injector -->
+  <!-- start class com.google.inject.Key -->
+  <class name="Key" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Key" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo} annotated with
+ {@code @Bar}:
+
+ <p>{@code new Key<Foo>(Bar.class) {}}.]]>
+      </doc>
+    </constructor>
+    <constructor name="Key" type="java.lang.annotation.Annotation"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo} annotated with
+ {@code @Bar}:
+
+ <p>{@code new Key<Foo>(new Bar()) {}}.]]>
+      </doc>
+    </constructor>
+    <constructor name="Key"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo}:
+
+ <p>{@code new Key<Foo>() {}}.]]>
+      </doc>
+    </constructor>
+    <method name="getTypeLiteral" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the key type.]]>
+      </doc>
+    </method>
+    <method name="getAnnotationType" return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the annotation type.]]>
+      </doc>
+    </method>
+    <method name="getAnnotation" return="java.lang.annotation.Annotation"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the annotation.]]>
+      </doc>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Binding key consisting of an injection type and an optional annotation.
+ Matches the type and annotation at a point of injection.
+
+ <p>For example, {@code Key.get(Service.class, Transactional.class)} will
+ match:
+
+ <pre>
+   {@literal @}Inject
+   public void setService({@literal @}Transactional Service service) {
+     ...
+   }
+ </pre>
+
+ <p>{@code Key} supports generic types via subclassing just like {@link
+ TypeLiteral}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Key -->
+  <!-- start interface com.google.inject.Module -->
+  <interface name="Module"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Contributes bindings and other configurations to a {@code Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A module contributes configuration information, typically interface
+ bindings, which will be used to create an {@link Injector}. A guice-based
+ application is ultimately composed of little more than a set of
+ {@code Module}s and some bootstrapping code.
+
+ <p>Your Module classes can use a more streamlined syntax by extending
+ {@link AbstractModule} rather than implementing this interface directly.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Module -->
+  <!-- start class com.google.inject.ProvidedBy -->
+  <class name="ProvidedBy"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A pointer to the default provider type for a type.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ProvidedBy -->
+  <!-- start interface com.google.inject.Provider -->
+  <interface name="Provider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="get" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Provides an instance of {@code T}. Must never return {@code null}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Simply, any object capable of providing instances of type {@code T}.
+ Providers are used in numerous ways by the Guice framework:
+
+ <ul>
+ <li>When the default means for obtaining instances (an injectable or
+ parameterless constructor) is insufficient for a particular binding, the
+ module can specify a custom {@code Provider} instead, to control exactly how
+ Guice creates or obtains instances for the binding.
+
+ <li>An implementation class may always choose to have a {@code Provider<T>}
+ instance injected, rather than having a {@code T} injected directly.  This
+ may give you access to multiple instances, instances you wish to safely
+ mutate and discard, instances which are out of scope (e.g. using a
+ {@code @RequestScoped} object from within a {@code @SessionScoped} object),
+ or instances you don't want to initialize until they are absolutely needed.
+
+ <li>A custom {@link Scope} is implemented as a decorator of
+ {@code Provider<T>}, which decides when to delegate to the backing provider
+ and when to provide the instance some other way.
+
+ <li>The {@link Injector} offers access to the {@code Provider<T>} it uses
+ to fulfill requests for a given key, via the {@link Injector#getProvider}
+ methods.
+ </ul>
+
+ @param <T> the type of object this provider provides
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Provider -->
+  <!-- start interface com.google.inject.Scope -->
+  <interface name="Scope"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="scope" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <param name="unscoped" type="com.google.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Scopes a provider. The returned locator returns objects from this scope. If
+ an object does not exist in this scope, the provider can use the given
+ unscoped provider to retrieve one.
+
+ <p>Scope implementations are strongly encouraged to override
+ {@link Object#toString} in the returned provider and include the backing
+ provider's {@code toString()} output.
+
+ @param key binding key
+ @param unscoped locates an instance when one doesn't already exist in this
+  scope.
+ @return a new provider which only delegates to the given unscoped provider
+  when an instance of the requested object doesn't already exist in this
+  scope]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[A short but useful description of this scope.  For comparison, the standard
+ scopes that ship with guice use the descriptions
+ {@code "Scopes.SINGLETON"}, {@code "ServletScopes.SESSION"} and
+ {@code "ServletScopes.REQUEST"}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A scope is a level of visibility that instances provided by Guice may have.
+ By default, an instance created by the {@link Injector} has <i>no
+ scope</i>, meaning it has no state from the framework's perspective -- the
+ {@code Injector} creates it, injects it once into the class that required it,
+ and then immediately forgets it. Associating a scope with a particular binding
+ allows the created instance to be "remembered" and possibly used again for
+ other injections.
+
+ @see Scopes#SINGLETON
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Scope -->
+  <!-- start class com.google.inject.ScopeAnnotation -->
+  <class name="ScopeAnnotation"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates annotations which are used for scoping. Only one such annotation
+ may apply to a single implementation class. You must also annotate scope
+ annotations with {@code @Retention(RUNTIME)}. For example:
+
+ <pre>
+   {@code @}Retention(RUNTIME)
+   {@code @}Target(TYPE)
+   {@code @}ScopeAnnotation
+   public {@code @}interface SessionScoped {}
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ScopeAnnotation -->
+  <!-- start class com.google.inject.Scopes -->
+  <class name="Scopes" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <field name="SINGLETON" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[One instance per {@link Injector}. Also see {@code @}{@link Singleton}.]]>
+      </doc>
+    </field>
+    <doc>
+    <![CDATA[Built in scope implementations.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Scopes -->
+  <!-- start class com.google.inject.Singleton -->
+  <class name="Singleton"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want only one instance
+ (per {@link Injector}) to be reused for all injections for that binding.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Singleton -->
+  <!-- start class com.google.inject.Stage -->
+  <class name="Stage" extends="java.lang.Enum&lt;com.google.inject.Stage&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.Stage[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[The stage we're running in.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Stage -->
+  <!-- start class com.google.inject.TypeLiteral -->
+  <class name="TypeLiteral" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="TypeLiteral"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new type literal. Derives represented class from type
+ parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.]]>
+      </doc>
+    </constructor>
+    <method name="getType" return="java.lang.reflect.Type"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets underlying {@code Type} instance.]]>
+      </doc>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Gets type literal for the given {@code Type} instance.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets type literal for the given {@code Class} instance.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Represents a generic type {@code T}. Java doesn't yet provide a way to
+ represent generic types, so this class does. Forces clients to create a
+ subclass of this class which enables retrieval the type information even at
+ runtime.
+
+ <p>For example, to create a type literal for {@code List<String>}, you can
+ create an empty anonymous inner class:
+
+ <p>
+ {@code TypeLiteral<List<String>> list = new TypeLiteral<List<String>>() {};}
+
+ <p>Assumes that type {@code T} implements {@link Object#equals} and
+ {@link Object#hashCode()} as value (as opposed to identity) comparison.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.TypeLiteral -->
+</package>
+<package name="com.google.inject.binder">
+  <!-- start interface com.google.inject.binder.AnnotatedBindingBuilder -->
+  <interface name="AnnotatedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"/>
+    <method name="annotatedWith" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Specifies an annotation type for this binding.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Specifies an annotation value for this binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Specifies the annotation for a binding. 
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedBindingBuilder -->
+  <!-- start interface com.google.inject.binder.AnnotatedConstantBindingBuilder -->
+  <interface name="AnnotatedConstantBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="annotatedWith" return="com.google.inject.binder.ConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Specifies an annotation type for this binding.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.binder.ConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Specifies an annotation value for this binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Specifies the annotation for a constant binding.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedConstantBindingBuilder -->
+  <!-- start interface com.google.inject.binder.ConstantBindingBuilder -->
+  <interface name="ConstantBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="int"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="long"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="boolean"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="double"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="float"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="short"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="char"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="E extends java.lang.Enum&lt;E&gt;"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Binds to a constant value.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.ConstantBindingBuilder -->
+  <!-- start interface com.google.inject.binder.LinkedBindingBuilder -->
+  <interface name="LinkedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.binder.ScopedBindingBuilder"/>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="implementation" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Binds to another binding with the specified type.]]>
+      </doc>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="implementation" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Binds to another binding with the specified type.]]>
+      </doc>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetKey" type="com.google.inject.Key&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Binds to another binding with the specified key.]]>
+      </doc>
+    </method>
+    <method name="toInstance"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Binds to the given instance. The Injector will automatically inject the
+ members of this instance when it is first created. See {@link
+ com.google.inject.Injector#injectMembers(Object)}.]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="provider" type="com.google.inject.Provider&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Binds to instances generated by the given Provider. The Injector will
+ automatically inject the members of this provider instance when it is first
+ created. See {@link com.google.inject.Injector#injectMembers(Object)}.]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerType" type="java.lang.Class&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[Binds to instances from the provider bound to the given provider type.]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerKey" type="com.google.inject.Key&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[Binds to instances from the provider bound to the given key.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Links a binding to another binding or an instance.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.LinkedBindingBuilder -->
+  <!-- start interface com.google.inject.binder.ScopedBindingBuilder -->
+  <interface name="ScopedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="in"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Specifies the scope. References the annotation passed to {@link
+ com.google.inject.Binder#bindScope(Class, com.google.inject.Scope)}.]]>
+      </doc>
+    </method>
+    <method name="in"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[Specifies the scope.]]>
+      </doc>
+    </method>
+    <method name="asEagerSingleton"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Instructs the {@link com.google.inject.Injector} to eagerly initialize this
+ singleton-scoped binding upon creation. Useful for application
+ initialization logic.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Specifies the scope for a binding.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.ScopedBindingBuilder -->
+</package>
+<package name="com.google.inject.jndi">
+  <!-- start class com.google.inject.jndi.JndiIntegration -->
+  <class name="JndiIntegration" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="fromJndi" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a provider which looks up objects in JNDI using the given name.
+ Example usage:
+
+ <pre>
+ bind(DataSource.class).toProvider(fromJndi(DataSource.class, "java:..."));
+ </pre>]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Integrates Guice with JNDI. Requires a binding to 
+ {@link javax.naming.Context}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.jndi.JndiIntegration -->
+</package>
+<package name="com.google.inject.matcher">
+  <!-- start class com.google.inject.matcher.AbstractMatcher -->
+  <class name="AbstractMatcher" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.matcher.Matcher&lt;T&gt;"/>
+    <constructor name="AbstractMatcher"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="and" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+    </method>
+    <method name="or" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[Implements {@code and()} and {@code or()}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.matcher.AbstractMatcher -->
+  <!-- start interface com.google.inject.matcher.Matcher -->
+  <interface name="Matcher"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="matches" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="T"/>
+      <doc>
+      <![CDATA[Returns {@code true} if this matches {@code t}, {@code false} otherwise.]]>
+      </doc>
+    </method>
+    <method name="and" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new matcher which returns {@code true} if both this and the
+ given matcher return {@code true}.]]>
+      </doc>
+    </method>
+    <method name="or" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new matcher which returns {@code true} if either this or the
+ given matcher return {@code true}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Returns {@code true} or {@code false} for a given input.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.matcher.Matcher -->
+  <!-- start class com.google.inject.matcher.Matchers -->
+  <class name="Matchers" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="any" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a matcher which matches any input.]]>
+      </doc>
+    </method>
+    <method name="not" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="p" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Inverts the given matcher.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches elements (methods, classes, etc.)
+ with a given annotation.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches elements (methods, classes, etc.)
+ with a given annotation.]]>
+      </doc>
+    </method>
+    <method name="subclassesOf" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="superclass" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches subclasses of the given type (as well as
+ the given type).]]>
+      </doc>
+    </method>
+    <method name="only" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches objects equal to the given object.]]>
+      </doc>
+    </method>
+    <method name="identicalTo" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches only the given object.]]>
+      </doc>
+    </method>
+    <method name="inPackage" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="p" type="java.lang.Package"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches classes in the given package.]]>
+      </doc>
+    </method>
+    <method name="returns" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.Method&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="returnType" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches methods with matching return types.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Matcher implementations. Supports matching classes and methods.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.matcher.Matchers -->
+</package>
+<package name="com.google.inject.name">
+  <!-- start class com.google.inject.name.Named -->
+  <class name="Named"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates named things.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.name.Named -->
+  <!-- start class com.google.inject.name.Names -->
+  <class name="Names" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="named" return="com.google.inject.name.Named"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a {@link Named} annotation with {@code name} as the value.]]>
+      </doc>
+    </method>
+    <method name="bindProperties"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="properties" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+      <doc>
+      <![CDATA[Creates a constant binding to {@code @Named(key)} for each property.]]>
+      </doc>
+    </method>
+    <method name="bindProperties"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="properties" type="java.util.Properties"/>
+      <doc>
+      <![CDATA[Creates a constant binding to {@code @Named(key)} for each property.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Utility methods for use with {@code @}{@link Named}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.name.Names -->
+</package>
+<package name="com.google.inject.servlet">
+  <!-- start class com.google.inject.servlet.GuiceFilter -->
+  <class name="GuiceFilter" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceFilter"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="doFilter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletRequest" type="ServletRequest"/>
+      <param name="servletResponse" type="ServletResponse"/>
+      <param name="filterChain" type="FilterChain"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="init"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterConfig" type="FilterConfig"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="destroy"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Apply this filter to all requests where you plan to use servlet scopes.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.GuiceFilter -->
+  <!-- start class com.google.inject.servlet.RequestParameters -->
+  <class name="RequestParameters"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to field or parameters of type {@code Map<String, String[]>}
+ when you want the HTTP request parameter map to be injected.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.RequestParameters -->
+  <!-- start class com.google.inject.servlet.RequestScoped -->
+  <class name="RequestScoped"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want one instance per request.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.RequestScoped -->
+  <!-- start class com.google.inject.servlet.ServletModule -->
+  <class name="ServletModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ServletModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Configures the servlet scopes and creates bindings for the servlet API
+ objects so you can inject the request, response, session, etc.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ServletModule -->
+  <!-- start class com.google.inject.servlet.ServletScopes -->
+  <class name="ServletScopes" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <field name="REQUEST" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[HTTP servlet request scope.]]>
+      </doc>
+    </field>
+    <field name="SESSION" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[HTTP session scope.]]>
+      </doc>
+    </field>
+    <doc>
+    <![CDATA[Servlet scopes.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ServletScopes -->
+  <!-- start class com.google.inject.servlet.SessionScoped -->
+  <class name="SessionScoped"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want one instance per session.
+
+ @see com.google.inject.Scopes#SINGLETON
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.SessionScoped -->
+</package>
+<package name="com.google.inject.spi">
+  <!-- start class com.google.inject.spi.Message -->
+  <class name="Message" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Message" type="java.lang.Object, java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="Message" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the source of the configuration which resulted in this error message.]]>
+      </doc>
+    </method>
+    <method name="getSourceString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a string representation of the source object.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the error message text.]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <doc>
+    <![CDATA[A message. Contains a source pointing to the code which resulted
+ in this message and a text message.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Message -->
+  <!-- start interface com.google.inject.spi.SourceProvider -->
+  <interface name="SourceProvider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="source" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates an object pointing to the current location within the
+ configuration. If we run into a problem later, we'll be able to trace it
+ back to the original source. Useful for debugging.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Provides source objects to the {@link com.google.inject.Binder}.
+ A source object is any object which points back to the current location
+ within the configuration. Guice uses source objects in error messages
+ and associates them with bindings.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.SourceProvider -->
+  <!-- start class com.google.inject.spi.SourceProviders -->
+  <class name="SourceProviders" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="skip"
+      abstract="false" native="false" synchronized="true"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Instructs stacktrace-based providers to skip the given class in the stack
+ trace when determining the source. Use this to keep the binder from
+ logging utility methods as the sources of bindings (i.e. it will skip to
+ the utility methods' callers instead).
+
+ <p>Skipping only takes place after this method is called.]]>
+      </doc>
+    </method>
+    <method name="getSkippedClassNames" return="java.util.Set&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="true"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the set of class names which should be skipped by stacktrace-based
+ providers.]]>
+      </doc>
+    </method>
+    <method name="defaultSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the current source obtained from the default provider.]]>
+      </doc>
+    </method>
+    <method name="withDefault"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="sourceProvider" type="com.google.inject.spi.SourceProvider"/>
+      <param name="r" type="java.lang.Runnable"/>
+      <doc>
+      <![CDATA[Sets the default source provider, runs the given command, and then
+ restores the previous default source provider.]]>
+      </doc>
+    </method>
+    <field name="UNKNOWN_SOURCE" type="java.lang.Object"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+    </field>
+    <doc>
+    <![CDATA[Provides access to the default {@link SourceProvider} implementation and
+ common controls for certain implementations.
+ 
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.SourceProviders -->
+</package>
+<package name="com.google.inject.spring">
+  <!-- start class com.google.inject.spring.SpringIntegration -->
+  <class name="SpringIntegration" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="fromSpring" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a provider which looks up objects from Spring using the given name.
+ Expects a binding to {@link
+ org.springframework.beans.factory.BeanFactory}. Example usage:
+
+ <pre>
+ bind(DataSource.class)
+   .toProvider(fromSpring(DataSource.class, "dataSource"));
+ </pre>]]>
+      </doc>
+    </method>
+    <method name="bindAll"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="beanFactory" type="ListableBeanFactory"/>
+      <doc>
+      <![CDATA[Binds all Spring beans from the given factory by name. For a Spring bean
+ named "foo", this method creates a binding to the bean's type and
+ {@code @Named("foo")}.
+
+ @see com.google.inject.name.Named
+ @see com.google.inject.name.Names#named(String)]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Integrates Guice with Spring.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spring.SpringIntegration -->
+</package>
+<package name="com.google.inject.struts2">
+  <!-- start class com.google.inject.struts2.GuiceObjectFactory -->
+  <class name="GuiceObjectFactory" extends="ObjectFactory"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceObjectFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="isNoArgConstructorRequired" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassInstance" return="java.lang.Class"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException"/>
+    </method>
+    <method name="buildBean" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class"/>
+      <param name="extraContext" type="java.util.Map"/>
+    </method>
+    <method name="buildInterceptor" return="Interceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorConfig" type="InterceptorConfig"/>
+      <param name="interceptorRefParams" type="java.util.Map"/>
+      <exception name="ConfigurationException" type="ConfigurationException"/>
+    </method>
+  </class>
+  <!-- end class com.google.inject.struts2.GuiceObjectFactory -->
+</package>
+<package name="com.google.inject.tools.jmx">
+  <!-- start interface com.google.inject.tools.jmx.ManagedBindingMBean -->
+  <interface name="ManagedBindingMBean"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSource" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the source of this binding.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the provider to which this binding is bound.]]>
+      </doc>
+    </method>
+    <method name="getKey" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the binding key.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[JMX interface to bindings.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.tools.jmx.ManagedBindingMBean -->
+  <!-- start class com.google.inject.tools.jmx.Manager -->
+  <class name="Manager" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Manager"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="manage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="domain" type="java.lang.String"/>
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Registers all the bindings of an Injector with the platform MBean server.
+ Consider using the name of your root {@link Module} class as the domain.]]>
+      </doc>
+    </method>
+    <method name="manage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="server" type="javax.management.MBeanServer"/>
+      <param name="domain" type="java.lang.String"/>
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Registers all the bindings of an Injector with the given MBean server.
+ Consider using the name of your root {@link Module} class as the domain.]]>
+      </doc>
+    </method>
+    <method name="main"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="args" type="java.lang.String[]"/>
+      <exception name="Exception" type="java.lang.Exception"/>
+      <doc>
+      <![CDATA[Run with no arguments for usage instructions.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Provides a JMX interface to Guice.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.tools.jmx.Manager -->
+</package>
+
+</api>
diff --git a/latest-api-diffs/2.0.xml b/latest-api-diffs/2.0.xml
new file mode 100644
index 0000000..f2db56d
--- /dev/null
+++ b/latest-api-diffs/2.0.xml
@@ -0,0 +1,6523 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<!-- on Tue May 19 17:01:55 PDT 2009 -->
+
+<api
+  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+  xsi:noNamespaceSchemaLocation='api.xsd'
+  name="2.0"
+  jdversion="1.1.1">
+
+<!--  Command line arguments =  -doclet jdiff.JDiff -docletpath /Applications/bin/jdiff-1.1.1/jdiff.jar:/Applications/bin/jdiff-1.1.1/xerces.jar -d /Users/jessewilson/Guice/guice-everything/api-diffs -classpath /usr/share/ant/lib/ant-launcher.jar:/usr/share/ant/lib/ant-jai.jar:/usr/share/ant/lib/ant-jmf.jar:/usr/share/ant/lib/ant-junit.jar:/usr/share/ant/lib/ant-nodeps.jar:/usr/share/ant/lib/ant-swing.jar:/usr/share/ant/lib/ant-testutil.jar:/usr/share/ant/lib/ant-trax.jar:/usr/share/ant/lib/ant.jar:/usr/share/ant/lib/junit.jar:/usr/share/ant/lib/xercesImpl.jar:/usr/share/ant/lib/xml-apis.jar -sourcepath /Users/jessewilson/Guice/google-guice/src:/Users/jessewilson/Guice/google-guice/extensions/jmx/src:/Users/jessewilson/Guice/google-guice/extensions/jndi/src:/Users/jessewilson/Guice/google-guice/extensions/assistedinject/src:/Users/jessewilson/Guice/google-guice/extensions/multibindings/src:/Users/jessewilson/Guice/google-guice/extensions/throwingproviders/src:/Users/jessewilson/Guice/google-guice/servlet/src:/Users/jessewilson/Guice/google-guice/spring/src:/Users/jessewilson/Guice/google-guice/struts2/plugin/src -apiname 2.0 -baseURI http://www.w3.org -apidir /Users/jessewilson/Guice/guice-everything/api-diffs -source 1.5 -->
+<package name="com.google.inject">
+  <!-- start class com.google.inject.AbstractModule -->
+  <class name="AbstractModule" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Module"/>
+    <constructor name="AbstractModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="true"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="builder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="configure"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Configures a {@link Binder} via the exposed methods.]]>
+      </doc>
+    </method>
+    <method name="binder" return="com.google.inject.Binder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets direct access to the underlying {@code Binder}.]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[@see Binder#bindScope(Class, Scope)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Key)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Class)]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#bindConstant()]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[@see Binder#install(Module)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[@see Binder#addError(String, Object[])]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Throwable)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Message)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[@see Binder#requestInjection(Object)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[@see Binder#requestStaticInjection(Class[])]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindInterceptor(com.google.inject.matcher.Matcher,
+  com.google.inject.matcher.Matcher,
+  org.aopalliance.intercept.MethodInterceptor[])]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Adds a dependency from this module to {@code key}. When the injector is
+ created, Guice will report an error if {@code key} cannot be injected.
+ Note that this requirement may be satisfied by implicit binding, such as
+ a public no-arguments constructor.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Adds a dependency from this module to {@code type}. When the injector is
+ created, Guice will report an error if {@code type} cannot be injected.
+ Note that this requirement may be satisfied by implicit binding, such as
+ a public no-arguments constructor.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Key)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Class)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[@see Binder#convertToTypes
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#currentStage() 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(Class)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(TypeLiteral)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[@see Binder#bindListener(com.google.inject.matcher.Matcher,
+  com.google.inject.spi.TypeListener)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A support class for {@link Module}s which reduces repetition and results in
+ a more readable configuration. Simply extend this class, implement {@link
+ #configure()}, and call the inherited methods which mirror those found in
+ {@link Binder}. For example:
+
+ <pre>
+ public class MyModule extends AbstractModule {
+   protected void configure() {
+     bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
+     bind(CreditCardPaymentService.class);
+     bind(PaymentService.class).to(CreditCardPaymentService.class);
+     bindConstant().annotatedWith(Names.named("port")).to(8080);
+   }
+ }
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.AbstractModule -->
+  <!-- start interface com.google.inject.Binder -->
+  <interface name="Binder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[Binds method interceptor[s] to methods matched by class and method matchers. A method is
+ eligible for interception if:
+
+ <ul>
+  <li>Guice created the instance the method is on</li>
+  <li>Neither the enclosing type nor the method is final</li>
+  <li>And the method is package-private, protected, or public</li>
+ </ul>
+
+ @param classMatcher matches classes the interceptor should apply to. For
+     example: {@code only(Runnable.class)}.
+ @param methodMatcher matches methods the interceptor should apply to. For
+     example: {@code annotatedWith(Transactional.class)}.
+ @param interceptors to bind]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[Binds a scope to an annotation.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject instance fields
+ and methods of the given object.
+
+ @param type of instance
+ @param instance for which members will be injected
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject instance fields
+ and methods of the given object.
+
+ @param instance for which members will be injected
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject static fields
+ and methods in the given classes.
+
+ @param types for which static members will be injected]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[Uses the given module to configure more bindings.]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the current stage.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[Records an error message which will be presented to the user at a later
+ time. Unlike throwing an exception, this enable us to continue
+ configuring the Injector and discover more errors. Uses {@link
+ String#format(String, Object[])} to insert the arguments into the
+ message.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[Records an exception, the full details of which will be logged, and the
+ message of which will be presented to the user at a later
+ time. If your Module calls something that you worry may fail, you should
+ catch the exception and pass it into this.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Records an error message to be presented to the user at a later time.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key.
+ The returned will not be valid until the {@link Injector} has been
+ created. The provider will throw an {@code IllegalStateException} if you
+ try to use it beforehand.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection type.
+ The returned provider will not be valid until the {@link Injector} has been
+ created. The provider will throw an {@code IllegalStateException} if you
+ try to use it beforehand.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ {@link Injector} has been created. The members injector will throw an {@code
+ IllegalStateException} if you try to use it beforehand.
+
+ @param typeLiteral type to get members injector for
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ {@link Injector} has been created. The members injector will throw an {@code
+ IllegalStateException} if you try to use it beforehand.
+
+ @param type type to get members injector for
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[Binds a type converter. The injector will use the given converter to
+ convert string constants to matching types as needed.
+
+ @param typeMatcher matches types the converter can handle
+ @param converter converts values
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[Registers a listener for injectable types. Guice will notify the listener when it encounters
+ injectable types matched by the given type matcher.
+
+ @param typeMatcher that matches injectable types the listener should be notified of
+ @param listener for injectable types matched by typeMatcher
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="withSource" return="com.google.inject.Binder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a binder that uses {@code source} as the reference location for
+ configuration errors. This is typically a {@link StackTraceElement}
+ for {@code .java} source but it could any binding source, such as the
+ path to a {@code .properties} file.
+
+ @param source any object representing the source location and has a
+     concise {@link Object#toString() toString()} value
+ @return a binder that shares its configuration with this binder
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="skipSources" return="com.google.inject.Binder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classesToSkip" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[Returns a binder that skips {@code classesToSkip} when identify the
+ calling code. The caller's {@link StackTraceElement} is used to locate
+ the source of configuration errors.
+
+ @param classesToSkip library classes that create bindings on behalf of
+      their clients.
+ @return a binder that shares its configuration with this binder.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="newPrivateBinder" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a new private child environment for bindings and other configuration. The returned
+ binder can be used to add and configuration information in this environment. See {@link
+ PrivateModule} for details.
+
+ @return a binder that inherits configuration from this binder. Only exposed configuration on
+      the returned binder will be visible to this binder.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Collects configuration information (primarily <i>bindings</i>) which will be
+ used to create an {@link Injector}. Guice provides this object to your
+ application's {@link Module} implementors so they may each contribute
+ their own bindings and other registrations.
+
+ <h3>The Guice Binding EDSL</h3>
+
+ Guice uses an <i>embedded domain-specific language</i>, or EDSL, to help you
+ create bindings simply and readably.  This approach is great for overall
+ usability, but it does come with a small cost: <b>it is difficult to
+ learn how to use the Binding EDSL by reading
+ method-level javadocs</b>.  Instead, you should consult the series of
+ examples below.  To save space, these examples omit the opening
+ {@code binder}, just as you will if your module extends
+ {@link AbstractModule}.
+
+ <pre>
+     bind(ServiceImpl.class);</pre>
+
+ This statement does essentially nothing; it "binds the {@code ServiceImpl}
+ class to itself" and does not change Guice's default behavior.  You may still
+ want to use this if you prefer your {@link Module} class to serve as an
+ explicit <i>manifest</i> for the services it provides.  Also, in rare cases,
+ Guice may be unable to validate a binding at injector creation time unless it
+ is given explicitly.
+
+ <pre>
+     bind(Service.class).to(ServiceImpl.class);</pre>
+
+ Specifies that a request for a {@code Service} instance with no binding
+ annotations should be treated as if it were a request for a
+ {@code ServiceImpl} instance. This <i>overrides</i> the function of any
+ {@link ImplementedBy @ImplementedBy} or {@link ProvidedBy @ProvidedBy}
+ annotations found on {@code Service}, since Guice will have already
+ "moved on" to {@code ServiceImpl} before it reaches the point when it starts
+ looking for these annotations.
+
+ <pre>
+     bind(Service.class).toProvider(ServiceProvider.class);</pre>
+
+ In this example, {@code ServiceProvider} must extend or implement
+ {@code Provider<Service>}. This binding specifies that Guice should resolve
+ an unannotated injection request for {@code Service} by first resolving an
+ instance of {@code ServiceProvider} in the regular way, then calling
+ {@link Provider#get get()} on the resulting Provider instance to obtain the
+ {@code Service} instance.
+
+ <p>The {@link Provider} you use here does not have to be a "factory"; that
+ is, a provider which always <i>creates</i> each instance it provides.
+ However, this is generally a good practice to follow.  You can then use
+ Guice's concept of {@link Scope scopes} to guide when creation should happen
+ -- "letting Guice work for you".
+
+ <pre>
+     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);</pre>
+
+ Like the previous example, but only applies to injection requests that use
+ the binding annotation {@code @Red}.  If your module also includes bindings
+ for particular <i>values</i> of the {@code @Red} annotation (see below),
+ then this binding will serve as a "catch-all" for any values of {@code @Red}
+ that have no exact match in the bindings.
+ 
+ <pre>
+     bind(ServiceImpl.class).in(Singleton.class);
+     // or, alternatively
+     bind(ServiceImpl.class).in(Scopes.SINGLETON);</pre>
+
+ Either of these statements places the {@code ServiceImpl} class into
+ singleton scope.  Guice will create only one instance of {@code ServiceImpl}
+ and will reuse it for all injection requests of this type.  Note that it is
+ still possible to bind another instance of {@code ServiceImpl} if the second
+ binding is qualified by an annotation as in the previous example.  Guice is
+ not overly concerned with <i>preventing</i> you from creating multiple
+ instances of your "singletons", only with <i>enabling</i> your application to
+ share only one instance if that's all you tell Guice you need.
+
+ <p><b>Note:</b> a scope specified in this way <i>overrides</i> any scope that
+ was specified with an annotation on the {@code ServiceImpl} class.
+ 
+ <p>Besides {@link Singleton}/{@link Scopes#SINGLETON}, there are
+ servlet-specific scopes available in
+ {@code com.google.inject.servlet.ServletScopes}, and your Modules can
+ contribute their own custom scopes for use here as well.
+
+ <pre>
+     bind(new TypeLiteral&lt;PaymentService&lt;CreditCard>>() {})
+         .to(CreditCardPaymentService.class);</pre>
+
+ This admittedly odd construct is the way to bind a parameterized type. It
+ tells Guice how to honor an injection request for an element of type
+ {@code PaymentService<CreditCard>}. The class
+ {@code CreditCardPaymentService} must implement the
+ {@code PaymentService<CreditCard>} interface.  Guice cannot currently bind or
+ inject a generic type, such as {@code Set<E>}; all type parameters must be
+ fully specified.
+
+ <pre>
+     bind(Service.class).toInstance(new ServiceImpl());
+     // or, alternatively
+     bind(Service.class).toInstance(SomeLegacyRegistry.getService());</pre>
+
+ In this example, your module itself, <i>not Guice</i>, takes responsibility
+ for obtaining a {@code ServiceImpl} instance, then asks Guice to always use
+ this single instance to fulfill all {@code Service} injection requests.  When
+ the {@link Injector} is created, it will automatically perform field
+ and method injection for this instance, but any injectable constructor on
+ {@code ServiceImpl} is simply ignored.  Note that using this approach results
+ in "eager loading" behavior that you can't control.
+
+ <pre>
+     bindConstant().annotatedWith(ServerHost.class).to(args[0]);</pre>
+
+ Sets up a constant binding. Constant injections must always be annotated.
+ When a constant binding's value is a string, it is eligile for conversion to
+ all primitive types, to {@link Enum#valueOf(Class, String) all enums}, and to
+ {@link Class#forName class literals}. Conversions for other types can be
+ configured using {@link #convertToTypes(Matcher, TypeConverter)
+ convertToTypes()}.
+
+ <pre>
+   {@literal @}Color("red") Color red; // A member variable (field)
+    . . .
+     red = MyModule.class.getDeclaredField("red").getAnnotation(Color.class);
+     bind(Service.class).annotatedWith(red).to(RedService.class);</pre>
+
+ If your binding annotation has parameters you can apply different bindings to
+ different specific values of your annotation.  Getting your hands on the
+ right instance of the annotation is a bit of a pain -- one approach, shown
+ above, is to apply a prototype annotation to a field in your module class, so
+ that you can read this annotation instance and give it to Guice.
+
+ <pre>
+     bind(Service.class)
+         .annotatedWith(Names.named("blue"))
+         .to(BlueService.class);</pre>
+
+ Differentiating by names is a common enough use case that we provided a
+ standard annotation, {@link com.google.inject.name.Named @Named}.  Because of
+ Guice's library support, binding by name is quite easier than in the
+ arbitrary binding annotation case we just saw.  However, remember that these
+ names will live in a single flat namespace with all the other names used in
+ your application.
+
+ <p>The above list of examples is far from exhaustive.  If you can think of
+ how the concepts of one example might coexist with the concepts from another,
+ you can most likely weave the two together.  If the two concepts make no
+ sense with each other, you most likely won't be able to do it.  In a few
+ cases Guice will let something bogus slip by, and will then inform you of
+ the problems at runtime, as soon as you try to create your Injector.
+
+ <p>The other methods of Binder such as {@link #bindScope},
+ {@link #bindInterceptor}, {@link #install}, {@link #requestStaticInjection},
+ {@link #addError} and {@link #currentStage} are not part of the Binding EDSL;
+ you can learn how to use these in the usual way, from the method
+ documentation.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @author kevinb@google.com (Kevin Bourrillion)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Binder -->
+  <!-- start interface com.google.inject.Binding -->
+  <interface name="Binding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for this binding.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the scoped provider guice uses to fulfill requests for this
+ binding.
+
+ @throws UnsupportedOperationException when invoked on a {@link Binding}
+      created via {@link com.google.inject.spi.Elements#getElements}. This
+      method is only supported on {@link Binding}s returned from an injector.]]>
+      </doc>
+    </method>
+    <method name="acceptTargetVisitor" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;? super T, V&gt;"/>
+      <doc>
+      <![CDATA[Accepts a target visitor. Invokes the visitor method specific to this binding's target.
+
+ @param visitor to call back on
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="acceptScopingVisitor" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Accepts a scoping visitor. Invokes the visitor method specific to this binding's scoping.
+
+ @param visitor to call back on
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A mapping from a key (type and optional annotation) to the strategy for getting instances of the
+ type. This interface is part of the introspection API and is intended primarily for use by 
+ tools.
+
+ <p>Bindings are created in several ways:
+ <ul>
+     <li>Explicitly in a module, via {@code bind()} and {@code bindConstant()}
+         statements:
+ <pre>
+     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);
+     bindConstant().annotatedWith(ServerHost.class).to(args[0]);</pre></li>
+     <li>Implicitly by the Injector by following a type's {@link ImplementedBy
+         pointer} {@link ProvidedBy annotations} or by using its {@link Inject annotated} or
+         default constructor.</li>
+     <li>By converting a bound instance to a different type.</li>
+     <li>For {@link Provider providers}, by delegating to the binding for the provided type.</li>
+ </ul>
+
+
+ <p>They exist on both modules and on injectors, and their behaviour is different for each:
+ <ul>
+     <li><strong>Module bindings</strong> are incomplete and cannot be used to provide instances.
+         This is because the applicable scopes and interceptors may not be known until an injector
+         is created. From a tool's perspective, module bindings are like the injector's source
+         code. They can be inspected or rewritten, but this analysis must be done statically.</li>
+     <li><strong>Injector bindings</strong> are complete and valid and can be used to provide
+         instances. From a tools' perspective, injector bindings are like reflection for an
+         injector. They have full runtime information, including the complete graph of injections
+         necessary to satisfy a binding.</li>
+ </ul>
+
+ @param <T> the bound type. The injected is always assignable to this type.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Binding -->
+  <!-- start class com.google.inject.BindingAnnotation -->
+  <class name="BindingAnnotation"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates annotations which are used for binding. Only one such annotation
+ may apply to a single injection point. You must also annotate binder
+ annotations with {@code @Retention(RUNTIME)}. For example:
+
+ <pre>
+   {@code @}Retention(RUNTIME)
+   {@code @}Target({ FIELD, PARAMETER, METHOD })
+   {@code @}BindingAnnotation
+   public {@code @}interface Transactional {}
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.BindingAnnotation -->
+  <!-- start class com.google.inject.ConfigurationException -->
+  <class name="ConfigurationException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ConfigurationException" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a ConfigurationException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <method name="withPartialValue" return="com.google.inject.ConfigurationException"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="partialValue" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a copy of this configuration exception with the specified partial value.]]>
+      </doc>
+    </method>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getPartialValue" return="E"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a value that was only partially computed due to this exception. The caller can use
+ this while collecting additional configuration problems.
+
+ @return the partial value, or {@code null} if none was set. The type of the partial value is
+      specified by the throwing method.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Thrown when a programming error such as a misplaced annotation, illegal binding, or unsupported
+ scope is found. Clients should catch this exception, log it, and stop execution.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ConfigurationException -->
+  <!-- start class com.google.inject.CreationException -->
+  <class name="CreationException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="CreationException" type="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a CreationException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Thrown when errors occur while creating a {@link Injector}. Includes a list of encountered
+ errors. Clients should catch this exception, log it, and stop execution.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.CreationException -->
+  <!-- start class com.google.inject.Exposed -->
+  <class name="Exposed"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Acccompanies a {@literal @}{@link com.google.inject.Provides Provides} method annotation in a
+ private module to indicate that the provided binding is exposed.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Exposed -->
+  <!-- start class com.google.inject.Guice -->
+  <class name="Guice" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules.
+
+ @throws CreationException if one or more errors occur during Injector
+     construction]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules.
+
+ @throws CreationException if one or more errors occur during Injector
+     creation]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules, in a given development
+ stage.
+
+ @throws CreationException if one or more errors occur during Injector
+     creation]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules, in a given development
+ stage.
+
+ @throws CreationException if one or more errors occur during Injector
+     construction]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[The entry point to the Guice framework. Creates {@link Injector}s from
+ {@link Module}s.
+
+ <p>Guice supports a model of development that draws clear boundaries between
+ APIs, Implementations of these APIs, Modules which configure these
+ implementations, and finally Applications which consist of a collection of
+ Modules. It is the Application, which typically defines your {@code main()}
+ method, that bootstraps the Guice Injector using the {@code Guice} class, as
+ in this example:
+ <pre>
+     public class FooApplication {
+       public static void main(String[] args) {
+         Injector injector = Guice.createInjector(
+             new ModuleA(),
+             new ModuleB(),
+             . . .
+             new FooApplicationFlagsModule(args)
+         );
+
+         // Now just bootstrap the application and you're done
+         FooStarter starter = injector.getInstance(FooStarter.class);
+         starter.runApplication();
+       }
+     }
+ </pre>]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Guice -->
+  <!-- start class com.google.inject.ImplementedBy -->
+  <class name="ImplementedBy"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A pointer to the default implementation of a type.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ImplementedBy -->
+  <!-- start class com.google.inject.Inject -->
+  <class name="Inject"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates members of your implementation class (constructors, methods
+ and fields) into which the {@link Injector} should inject values.
+ The Injector fulfills injection requests for:
+
+ <ul>
+ <li>Every instance it constructs. The class being constructed must have
+ exactly one of its constructors marked with {@code @Inject} or must have a
+ constructor taking no parameters. The Injector then proceeds to perform
+ method and field injections.
+ 
+ <li>Pre-constructed instances passed to {@link Injector#injectMembers},
+ {@link com.google.inject.binder.LinkedBindingBuilder#toInstance(Object)} and
+ {@link com.google.inject.binder.LinkedBindingBuilder#toProvider(Provider)}.
+ In this case all constructors are, of course, ignored.
+
+ <li>Static fields and methods of classes which any {@link Module} has
+ specifically requested static injection for, using
+ {@link Binder#requestStaticInjection}.
+ </ul>
+
+ In all cases, a member can be injected regardless of its Java access
+ specifier (private, default, protected, public).
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Inject -->
+  <!-- start interface com.google.inject.Injector -->
+  <interface name="Injector"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="injectMembers"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
+ absence of an injectable constructor.
+
+ <p>Whenever Guice creates an instance, it performs this injection automatically (after first
+ performing constructor injection), so if you're able to let Guice create all your objects for
+ you, you'll never need to use this method.
+
+ @param instance to inject members on
+
+ @see Binder#getMembersInjector(Class) for a preferred alternative that supports checks before
+  run time]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}.
+
+ @param typeLiteral type to get members injector for
+ @see Binder#getMembersInjector(TypeLiteral) for an alternative that offers up front error
+  detection
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. When feasible, use {@link Binder#getMembersInjector(TypeLiteral)}
+ instead to get increased up front error detection.
+
+ @param type type to get members injector for
+ @see Binder#getMembersInjector(Class) for an alternative that offers up front error
+  detection
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getBindings" return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all explicit bindings.
+
+ <p>The returned map does not include bindings inherited from a {@link #getParent() parent
+ injector}, should one exist. The returned map is guaranteed to iterate (for example, with
+ its {@link java.util.Map#entrySet()} iterator) in the order of insertion. In other words,
+ the order in which bindings appear in user Modules.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.]]>
+      </doc>
+    </method>
+    <method name="getBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the binding for the given injection key. This will be an explicit bindings if the key
+ was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
+ be created if necessary.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+
+ @throws ConfigurationException if this injector cannot find or create the binding.]]>
+      </doc>
+    </method>
+    <method name="getBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the binding for the given type. This will be an explicit bindings if the injection key
+ was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
+ be created if necessary.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+
+ @throws ConfigurationException if this injector cannot find or create the binding.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="findBindingsByType" return="java.util.List&lt;com.google.inject.Binding&lt;T&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns all explicit bindings for {@code type}.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key. When feasible, avoid
+ using this method, in favor of having Guice inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @see Binder#getProvider(Key) for an alternative that offers up front error detection]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given type. When feasible, avoid
+ using this method, in favor of having Guice inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @see Binder#getProvider(Class) for an alternative that offers up front error detection]]>
+      </doc>
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the appropriate instance for the given injection key; equivalent to {@code
+ getProvider(key).get()}. When feasible, avoid using this method, in favor of having Guice
+ inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @throws ProvisionException if there was a runtime failure while providing an instance.]]>
+      </doc>
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the appropriate instance for the given injection type; equivalent to {@code
+ getProvider(type).get()}. When feasible, avoid using this method, in favor of having Guice
+ inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @throws ProvisionException if there was a runtime failure while providing an instance.]]>
+      </doc>
+    </method>
+    <method name="getParent" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns this injector's parent, or {@code null} if this is a top-level injector.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="createChildInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injector that inherits all state from this injector. All bindings, scopes,
+ interceptors and type converters are inherited -- they are visible to the child injector.
+ Elements of the child injector are not visible to its parent.
+
+ <p>Just-in-time bindings created for child injectors will be created in an ancestor injector
+ whenever possible. This allows for scoped instances to be shared between injectors. Use
+ explicit bindings to prevent bindings from being shared with the parent injector.
+
+ <p>No key may be bound by both an injector and one of its ancestors. This includes just-in-time
+ bindings. The lone exception is the key for {@code Injector.class}, which is bound by each
+ injector to itself.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="createChildInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a new injector that inherits all state from this injector. All bindings, scopes,
+ interceptors and type converters are inherited -- they are visible to the child injector.
+ Elements of the child injector are not visible to its parent.
+
+ <p>Just-in-time bindings created for child injectors will be created in an ancestor injector
+ whenever possible. This allows for scoped instances to be shared between injectors. Use
+ explicit bindings to prevent bindings from being shared with the parent injector.
+
+ <p>No key may be bound by both an injector and one of its ancestors. This includes just-in-time
+ bindings. The lone exception is the key for {@code Injector.class}, which is bound by each
+ injector to itself.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Builds the graphs of objects that make up your application. The injector tracks the dependencies
+ for each type and uses bindings to inject them. This is the core of Guice, although you rarely
+ interact with it directly. This "behind-the-scenes" operation is what distinguishes dependency
+ injection from its cousin, the service locator pattern.
+
+ <p>Contains several default bindings:
+
+ <ul>
+ <li>This {@link Injector} instance itself
+ <li>A {@code Provider<T>} for each binding of type {@code T}
+ <li>The {@link java.util.logging.Logger} for the class being injected
+ <li>The {@link Stage} in which the Injector was created
+ </ul>
+
+ Injectors are created using the facade class {@link Guice}.
+
+ <p>An injector can also {@link #injectMembers(Object) inject the dependencies} of
+ already-constructed instances. This can be used to interoperate with objects created by other
+ frameworks or services.
+
+ <p>Injectors can be {@link #createChildInjector(Iterable) hierarchical}. Child injectors inherit
+ the configuration of their parent injectors, but the converse does not hold.
+
+ <p>The injector's {@link #getBindings() internal bindings} are available for introspection. This
+ enables tools and extensions to operate on an injector reflectively.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Injector -->
+  <!-- start class com.google.inject.Key -->
+  <class name="Key" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Key" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo} annotated with
+ {@code @Bar}:
+
+ <p>{@code new Key<Foo>(Bar.class) {}}.]]>
+      </doc>
+    </constructor>
+    <constructor name="Key" type="java.lang.annotation.Annotation"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo} annotated with
+ {@code @Bar}:
+
+ <p>{@code new Key<Foo>(new Bar()) {}}.]]>
+      </doc>
+    </constructor>
+    <constructor name="Key"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo}:
+
+ <p>{@code new Key<Foo>() {}}.]]>
+      </doc>
+    </constructor>
+    <method name="getTypeLiteral" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the key type.]]>
+      </doc>
+    </method>
+    <method name="getAnnotationType" return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the annotation type.]]>
+      </doc>
+    </method>
+    <method name="getAnnotation" return="java.lang.annotation.Annotation"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the annotation.]]>
+      </doc>
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Binding key consisting of an injection type and an optional annotation.
+ Matches the type and annotation at a point of injection.
+
+ <p>For example, {@code Key.get(Service.class, Transactional.class)} will
+ match:
+
+ <pre>
+   {@literal @}Inject
+   public void setService({@literal @}Transactional Service service) {
+     ...
+   }
+ </pre>
+
+ <p>{@code Key} supports generic types via subclassing just like {@link
+ TypeLiteral}.
+
+ <p>Keys do not differentiate between primitive types (int, char, etc.) and
+ their correpsonding wrapper types (Integer, Character, etc.). Primitive
+ types will be replaced with their wrapper types when keys are created.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Key -->
+  <!-- start interface com.google.inject.MembersInjector -->
+  <interface name="MembersInjector"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="injectMembers"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
+ absence of an injectable constructor.
+
+ <p>Whenever Guice creates an instance, it performs this injection automatically (after first
+ performing constructor injection), so if you're able to let Guice create all your objects for
+ you, you'll never need to use this method.
+
+ @param instance to inject members on. May be {@code null}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Injects dependencies into the fields and methods on instances of type {@code T}. Ignores the
+ presence or absence of an injectable constructor.
+
+ @param <T> type to inject members of
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.MembersInjector -->
+  <!-- start interface com.google.inject.Module -->
+  <interface name="Module"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Contributes bindings and other configurations for this module to {@code binder}.
+
+ <p><strong>Do not invoke this method directly</strong> to install submodules. Instead use
+ {@link Binder#install(Module)}, which ensures that {@link Provides provider methods} are
+ discovered.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A module contributes configuration information, typically interface
+ bindings, which will be used to create an {@link Injector}. A Guice-based
+ application is ultimately composed of little more than a set of
+ {@code Module}s and some bootstrapping code.
+
+ <p>Your Module classes can use a more streamlined syntax by extending
+ {@link AbstractModule} rather than implementing this interface directly.
+
+ <p>In addition to the bindings configured via {@link #configure}, bindings
+ will be created for all methods annotated with {@literal @}{@link Provides}.
+ Use scope and binding annotations on these methods to configure the
+ bindings.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Module -->
+  <!-- start class com.google.inject.OutOfScopeException -->
+  <class name="OutOfScopeException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="OutOfScopeException" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="OutOfScopeException" type="java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="OutOfScopeException" type="java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <doc>
+    <![CDATA[Thrown from {@link Provider#get} when an attempt is made to access a scoped
+ object while the scope in question is not currently active.
+
+ @author kevinb@google.com (Kevin Bourrillion)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.OutOfScopeException -->
+  <!-- start interface com.google.inject.PrivateBinder -->
+  <interface name="PrivateBinder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binder"/>
+    <method name="expose"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes the binding for {@code key} available to the enclosing environment]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to the enclosing environment. Use {@link
+ com.google.inject.binder.AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to the enclosing environment. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="withSource" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <method name="skipSources" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classesToSkip" type="java.lang.Class[]"/>
+    </method>
+    <doc>
+    <![CDATA[Returns a binder whose configuration information is hidden from its environment by default. See
+ {@link com.google.inject.PrivateModule PrivateModule} for details.
+ 
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.PrivateBinder -->
+  <!-- start class com.google.inject.PrivateModule -->
+  <class name="PrivateModule" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Module"/>
+    <constructor name="PrivateModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="true"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="configure"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates bindings and other configurations private to this module. Use {@link #expose(Class)
+ expose()} to make the bindings in this module available externally.]]>
+      </doc>
+    </method>
+    <method name="expose"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Makes the binding for {@code key} available to other modules and the injector.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to other modules and the injector. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to other modules and the injector. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="binder" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the current binder.]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[@see Binder#bindScope(Class, Scope)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Key)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Class)]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#bindConstant()]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[@see Binder#install(Module)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[@see Binder#addError(String, Object[])]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Throwable)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Message)]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[@see Binder#requestInjection(Object)]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[@see Binder#requestStaticInjection(Class[])]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindInterceptor(com.google.inject.matcher.Matcher, com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Instructs Guice to require a binding to the given key.]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Instructs Guice to require a binding to the given type.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Key)]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Class)]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[@see Binder#convertToTypes(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeConverter)]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#currentStage()]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(Class)]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[@see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener)]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A module whose configuration information is hidden from its environment by default. Only bindings
+ that are explicitly exposed will be available to other modules and to the users of the injector.
+ This module may expose the bindings it creates and the bindings of the modules it installs.
+
+ <p>A private module can be nested within a regular module or within another private module using
+ {@link Binder#install install()}.  Its bindings live in a new environment that inherits bindings,
+ type converters, scopes, and interceptors from the surrounding ("parent") environment.  When you
+ nest multiple private modules, the result is a tree of environments where the injector's
+ environment is the root.
+
+ <p>Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link
+ com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link
+ Exposed} annotation:
+
+ <pre>
+ public class FooBarBazModule extends PrivateModule {
+   protected void configure() {
+     bind(Foo.class).to(RealFoo.class);
+     expose(Foo.class);
+
+     install(new TransactionalBarModule());
+     expose(Bar.class).annotatedWith(Transactional.class);
+
+     bind(SomeImplementationDetail.class);
+     install(new MoreImplementationDetailsModule());
+   }
+
+   {@literal @}Provides {@literal @}Exposed
+   public Baz provideBaz() {
+     return new SuperBaz();
+   }
+ }
+ </pre>
+
+ <p>Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent
+ injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the
+ root environment. Such bindings are shared among all environments in the tree.
+ 
+ <p>The scope of a binding is constrained to its environment. A singleton bound in a private
+ module will be unique to its environment. But a binding for the same type in a different private
+ module will yield a different instance.
+
+ <p>A shared binding that injects the {@code Injector} gets the root injector, which only has
+ access to bindings in the root environment. An explicit binding that injects the {@code Injector}
+ gets access to all bindings in the child environment.
+
+ <p>To promote a just-in-time binding to an explicit binding, bind it:
+ <pre>
+   bind(FooImpl.class);
+ </pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.PrivateModule -->
+  <!-- start class com.google.inject.ProvidedBy -->
+  <class name="ProvidedBy"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A pointer to the default provider type for a type.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ProvidedBy -->
+  <!-- start interface com.google.inject.Provider -->
+  <interface name="Provider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="get" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Provides an instance of {@code T}. Must never return {@code null}.
+
+ @throws OutOfScopeException when an attempt is made to access a scoped object while the scope
+     in question is not currently active
+ @throws ProvisionException if an instance cannot be provided. Such exceptions include messages
+     and throwables to describe why provision failed.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An object capable of providing instances of type {@code T}. Providers are used in numerous ways
+ by Guice:
+
+ <ul>
+ <li>When the default means for obtaining instances (an injectable or parameterless constructor)
+ is insufficient for a particular binding, the module can specify a custom {@code Provider}
+ instead, to control exactly how Guice creates or obtains instances for the binding.
+
+ <li>An implementation class may always choose to have a {@code Provider<T>} instance injected,
+ rather than having a {@code T} injected directly.  This may give you access to multiple
+ instances, instances you wish to safely mutate and discard, instances which are out of scope
+ (e.g. using a {@code @RequestScoped} object from within a {@code @SessionScoped} object), or
+ instances that will be initialized lazily.
+
+ <li>A custom {@link Scope} is implemented as a decorator of {@code Provider<T>}, which decides
+ when to delegate to the backing provider and when to provide the instance some other way.
+
+ <li>The {@link Injector} offers access to the {@code Provider<T>} it uses to fulfill requests
+ for a given key, via the {@link Injector#getProvider} methods.
+ </ul>
+
+ @param <T> the type of object this provides
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Provider -->
+  <!-- start class com.google.inject.Provides -->
+  <class name="Provides"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates methods of a {@link Module} to create a provider method binding. The method's return
+ type is bound to it's returned value. Guice will pass dependencies to the method as parameters.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Provides -->
+  <!-- start class com.google.inject.ProvisionException -->
+  <class name="ProvisionException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ProvisionException" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a ConfigurationException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <constructor name="ProvisionException" type="java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="ProvisionException" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Indicates that there was a runtime failure while providing an instance.
+
+ @author kevinb@google.com (Kevin Bourrillion)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ProvisionException -->
+  <!-- start interface com.google.inject.Scope -->
+  <interface name="Scope"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="scope" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <param name="unscoped" type="com.google.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Scopes a provider. The returned provider returns objects from this scope.
+ If an object does not exist in this scope, the provider can use the given
+ unscoped provider to retrieve one.
+
+ <p>Scope implementations are strongly encouraged to override
+ {@link Object#toString} in the returned provider and include the backing
+ provider's {@code toString()} output.
+
+ @param key binding key
+ @param unscoped locates an instance when one doesn't already exist in this
+  scope.
+ @return a new provider which only delegates to the given unscoped provider
+  when an instance of the requested object doesn't already exist in this
+  scope]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[A short but useful description of this scope.  For comparison, the standard
+ scopes that ship with guice use the descriptions
+ {@code "Scopes.SINGLETON"}, {@code "ServletScopes.SESSION"} and
+ {@code "ServletScopes.REQUEST"}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A scope is a level of visibility that instances provided by Guice may have.
+ By default, an instance created by the {@link Injector} has <i>no scope</i>,
+ meaning it has no state from the framework's perspective -- the
+ {@code Injector} creates it, injects it once into the class that required it,
+ and then immediately forgets it. Associating a scope with a particular
+ binding allows the created instance to be "remembered" and possibly used
+ again for other injections.
+
+ <p>An example of a scope is {@link Scopes#SINGLETON}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Scope -->
+  <!-- start class com.google.inject.ScopeAnnotation -->
+  <class name="ScopeAnnotation"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates annotations which are used for scoping. Only one such annotation
+ may apply to a single implementation class. You must also annotate scope
+ annotations with {@code @Retention(RUNTIME)}. For example:
+
+ <pre>
+   {@code @}Retention(RUNTIME)
+   {@code @}Target(TYPE)
+   {@code @}ScopeAnnotation
+   public {@code @}interface SessionScoped {}
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ScopeAnnotation -->
+  <!-- start class com.google.inject.Scopes -->
+  <class name="Scopes" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <field name="SINGLETON" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[One instance per {@link Injector}. Also see {@code @}{@link Singleton}.]]>
+      </doc>
+    </field>
+    <field name="NO_SCOPE" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[No scope; the same as not applying any scope at all.  Each time the
+ Injector obtains an instance of an object with "no scope", it injects this
+ instance then immediately forgets it.  When the next request for the same
+ binding arrives it will need to obtain the instance over again.
+
+ <p>This exists only in case a class has been annotated with a scope
+ annotation such as {@link Singleton @Singleton}, and you need to override
+ this to "no scope" in your binding.
+
+ @since 2.0]]>
+      </doc>
+    </field>
+    <doc>
+    <![CDATA[Built-in scope implementations.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Scopes -->
+  <!-- start class com.google.inject.Singleton -->
+  <class name="Singleton"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want only one instance
+ (per {@link Injector}) to be reused for all injections for that binding.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Singleton -->
+  <!-- start class com.google.inject.Stage -->
+  <class name="Stage" extends="java.lang.Enum&lt;com.google.inject.Stage&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.Stage[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[The stage we're running in.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Stage -->
+  <!-- start class com.google.inject.TypeLiteral -->
+  <class name="TypeLiteral" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="TypeLiteral"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new type literal. Derives represented class from type
+ parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.]]>
+      </doc>
+    </constructor>
+    <method name="getRawType" return="java.lang.Class&lt;? super T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the raw (non-generic) type for this type.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getType" return="java.lang.reflect.Type"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets underlying {@code Type} instance.]]>
+      </doc>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Gets type literal for the given {@code Type} instance.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets type literal for the given {@code Class} instance.]]>
+      </doc>
+    </method>
+    <method name="getSupertype" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="supertype" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns the generic form of {@code supertype}. For example, if this is {@code
+ ArrayList<String>}, this returns {@code Iterable<String>} given the input {@code
+ Iterable.class}.
+
+ @param supertype a superclass of, or interface implemented by, this.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getFieldType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="field" type="java.lang.reflect.Field"/>
+      <doc>
+      <![CDATA[Returns the resolved generic type of {@code field}.
+
+ @param field a field defined by this or any superclass.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getParameterTypes" return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodOrConstructor" type="java.lang.reflect.Member"/>
+      <doc>
+      <![CDATA[Returns the resolved generic parameter types of {@code methodOrConstructor}.
+
+ @param methodOrConstructor a method or constructor defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getExceptionTypes" return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodOrConstructor" type="java.lang.reflect.Member"/>
+      <doc>
+      <![CDATA[Returns the resolved generic exception types thrown by {@code constructor}.
+
+ @param methodOrConstructor a method or constructor defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getReturnType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="method" type="java.lang.reflect.Method"/>
+      <doc>
+      <![CDATA[Returns the resolved generic return type of {@code method}.
+
+ @param method a method defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Represents a generic type {@code T}. Java doesn't yet provide a way to
+ represent generic types, so this class does. Forces clients to create a
+ subclass of this class which enables retrieval the type information even at
+ runtime.
+
+ <p>For example, to create a type literal for {@code List<String>}, you can
+ create an empty anonymous inner class:
+
+ <p>
+ {@code TypeLiteral<List<String>> list = new TypeLiteral<List<String>>() {};}
+
+ <p>This syntax cannot be used to create type literals that have wildcard
+ parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
+ Such type literals must be constructed programatically, either by {@link
+ Method#getGenericReturnType extracting types from members} or by using the
+ {@link Types} factory class.
+
+ <p>Along with modeling generic types, this class can resolve type parameters.
+ For example, to figure out what type {@code keySet()} returns on a {@code
+ Map<Integer, String>}, use this code:<pre>   {@code
+
+   TypeLiteral<Map<Integer, String>> mapType
+       = new TypeLiteral<Map<Integer, String>>() {};
+   TypeLiteral<?> keySetType
+       = mapType.getReturnType(Map.class.getMethod("keySet"));
+   System.out.println(keySetType); // prints "Set<Integer>"}</pre>
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.TypeLiteral -->
+</package>
+<package name="com.google.inject.assistedinject">
+  <!-- start class com.google.inject.assistedinject.Assisted -->
+  <class name="Assisted"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates an injected parameter or field whose value comes from an argument to a factory method.
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.Assisted -->
+  <!-- start class com.google.inject.assistedinject.AssistedInject -->
+  <class name="AssistedInject"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="{@link FactoryProvider} now works better with the standard {@literal @Inject}
+     annotation. When using that annotation, parameters are matched by name and type rather than
+     by position. In addition, values that use the standard {@literal @Inject} constructor
+     annotation are eligible for method interception.">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[<p>Constructors annotated with {@code @AssistedInject} indicate that they can be instantiated by
+ the {@link FactoryProvider}. Each constructor must exactly match one corresponding factory method
+ within the factory interface.
+ 
+ <p>Constructor parameters must be either supplied by the factory interface and marked with
+ <code>@Assisted</code>, or they must be injectable.
+ 
+ @deprecated {@link FactoryProvider} now works better with the standard {@literal @Inject}
+     annotation. When using that annotation, parameters are matched by name and type rather than
+     by position. In addition, values that use the standard {@literal @Inject} constructor
+     annotation are eligible for method interception.
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.AssistedInject -->
+  <!-- start class com.google.inject.assistedinject.FactoryProvider -->
+  <class name="FactoryProvider" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Provider&lt;F&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="newFactory" return="com.google.inject.Provider&lt;F&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryType" type="java.lang.Class&lt;F&gt;"/>
+      <param name="implementationType" type="java.lang.Class&lt;?&gt;"/>
+    </method>
+    <method name="newFactory" return="com.google.inject.Provider&lt;F&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryType" type="com.google.inject.TypeLiteral&lt;F&gt;"/>
+      <param name="implementationType" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+    </method>
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="F"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Provides a factory that combines the caller's arguments with injector-supplied values to
+ construct objects.
+
+ <h3>Defining a factory</h3>
+ Create an interface whose methods return the constructed type, or any of its supertypes. The
+ method's parameters are the arguments required to build the constructed type.
+ <pre>public interface PaymentFactory {
+   Payment create(Date startDate, Money amount);
+ }</pre>
+ You can name your factory methods whatever you like, such as <i>create</i>, <i>createPayment</i>
+ or <i>newPayment</i>.
+
+ <h3>Creating a type that accepts factory parameters</h3>
+ {@code constructedType} is a concrete class with an {@literal @}{@link Inject}-annotated
+ constructor. In addition to injector-supplied parameters, the constructor should have
+ parameters that match each of the factory method's parameters. Each factory-supplied parameter
+ requires an {@literal @}{@link Assisted} annotation. This serves to document that the parameter
+ is not bound by your application's modules.
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted Date startDate</strong>,
+      <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }
+ }</pre>
+ Any parameter that permits a null value should also be annotated {@code @Nullable}.
+
+ <h3>Configuring factories</h3>
+ In your {@link com.google.inject.Module module}, bind the factory interface to the returned
+ factory:
+ <pre>bind(PaymentFactory.class).toProvider(
+     FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));</pre>
+ As a side-effect of this binding, Guice will inject the factory to initialize it for use. The
+ factory cannot be used until the injector has been initialized.
+
+ <h3>Using the factory</h3>
+ Inject your factory into your application classes. When you use the factory, your arguments
+ will be combined with values from the injector to construct an instance.
+ <pre>public class PaymentAction {
+   {@literal @}Inject private PaymentFactory paymentFactory;
+
+   public void doPayment(Money amount) {
+     Payment payment = paymentFactory.create(new Date(), amount);
+     payment.apply();
+   }
+ }</pre>
+
+ <h3>Making parameter types distinct</h3>
+ The types of the factory method's parameters must be distinct. To use multiple parameters of
+ the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the
+ parameters. The names must be applied to the factory method's parameters:
+
+ <pre>public interface PaymentFactory {
+   Payment create(
+       <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+       <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+       Money amount);
+ } </pre>
+ ...and to the concrete type's constructor parameters:
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+      <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+      <strong>{@literal @}Assisted</strong> Money amount) {
+     ...
+   }
+ }</pre>
+
+ <h3>Values are created by Guice</h3>
+ Returned factories use child injectors to create values. The values are eligible for method
+ interception. In addition, {@literal @}{@literal Inject} members will be injected before they are
+ returned.
+
+ <h3>Backwards compatibility using {@literal @}AssistedInject</h3>
+ Instead of the {@literal @}Inject annotation, you may annotate the constructed classes with
+ {@literal @}{@link AssistedInject}. This triggers a limited backwards-compatability mode.
+
+ <p>Instead of matching factory method arguments to constructor parameters using their names, the
+ <strong>parameters are matched by their order</strong>. The first factory method argument is
+ used for the first {@literal @}Assisted constructor parameter, etc.. Annotation names have no
+ effect.
+
+ <p>Returned values are <strong>not created by Guice</strong>. These types are not eligible for
+ method interception. They do receive post-construction member injection.
+
+ @param <F> The factory interface
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)
+ @author dtm@google.com (Daniel Martin)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.FactoryProvider -->
+</package>
+<package name="com.google.inject.binder">
+  <!-- start interface com.google.inject.binder.AnnotatedBindingBuilder -->
+  <interface name="AnnotatedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"/>
+    <method name="annotatedWith" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedBindingBuilder -->
+  <!-- start interface com.google.inject.binder.AnnotatedConstantBindingBuilder -->
+  <interface name="AnnotatedConstantBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="annotatedWith" return="com.google.inject.binder.ConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.binder.ConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedConstantBindingBuilder -->
+  <!-- start interface com.google.inject.binder.AnnotatedElementBuilder -->
+  <interface name="AnnotatedElementBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="annotatedWith"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedElementBuilder -->
+  <!-- start interface com.google.inject.binder.ConstantBindingBuilder -->
+  <interface name="ConstantBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="int"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="long"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="boolean"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="double"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="float"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="short"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="char"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="E extends java.lang.Enum&lt;E&gt;"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Binds to a constant value.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.ConstantBindingBuilder -->
+  <!-- start interface com.google.inject.binder.LinkedBindingBuilder -->
+  <interface name="LinkedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.binder.ScopedBindingBuilder"/>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="implementation" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="implementation" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetKey" type="com.google.inject.Key&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toInstance"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @see com.google.inject.Injector#injectMembers]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="provider" type="com.google.inject.Provider&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @see com.google.inject.Injector#injectMembers]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerType" type="java.lang.Class&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerKey" type="com.google.inject.Key&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.LinkedBindingBuilder -->
+  <!-- start interface com.google.inject.binder.ScopedBindingBuilder -->
+  <interface name="ScopedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="in"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="in"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="asEagerSingleton"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Instructs the {@link com.google.inject.Injector} to eagerly initialize this
+ singleton-scoped binding upon creation. Useful for application
+ initialization logic.  See the EDSL examples at
+ {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.ScopedBindingBuilder -->
+</package>
+<package name="com.google.inject.jndi">
+  <!-- start class com.google.inject.jndi.JndiIntegration -->
+  <class name="JndiIntegration" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="fromJndi" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a provider which looks up objects in JNDI using the given name.
+ Example usage:
+
+ <pre>
+ bind(DataSource.class).toProvider(fromJndi(DataSource.class, "java:..."));
+ </pre>]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Integrates Guice with JNDI. Requires a binding to 
+ {@link javax.naming.Context}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.jndi.JndiIntegration -->
+</package>
+<package name="com.google.inject.matcher">
+  <!-- start class com.google.inject.matcher.AbstractMatcher -->
+  <class name="AbstractMatcher" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.matcher.Matcher&lt;T&gt;"/>
+    <constructor name="AbstractMatcher"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="and" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+    </method>
+    <method name="or" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[Implements {@code and()} and {@code or()}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.matcher.AbstractMatcher -->
+  <!-- start interface com.google.inject.matcher.Matcher -->
+  <interface name="Matcher"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="matches" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="T"/>
+      <doc>
+      <![CDATA[Returns {@code true} if this matches {@code t}, {@code false} otherwise.]]>
+      </doc>
+    </method>
+    <method name="and" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new matcher which returns {@code true} if both this and the
+ given matcher return {@code true}.]]>
+      </doc>
+    </method>
+    <method name="or" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new matcher which returns {@code true} if either this or the
+ given matcher return {@code true}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Returns {@code true} or {@code false} for a given input.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.matcher.Matcher -->
+  <!-- start class com.google.inject.matcher.Matchers -->
+  <class name="Matchers" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="any" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a matcher which matches any input.]]>
+      </doc>
+    </method>
+    <method name="not" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="p" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Inverts the given matcher.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches elements (methods, classes, etc.)
+ with a given annotation.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches elements (methods, classes, etc.)
+ with a given annotation.]]>
+      </doc>
+    </method>
+    <method name="subclassesOf" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="superclass" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches subclasses of the given type (as well as
+ the given type).]]>
+      </doc>
+    </method>
+    <method name="only" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches objects equal to the given object.]]>
+      </doc>
+    </method>
+    <method name="identicalTo" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches only the given object.]]>
+      </doc>
+    </method>
+    <method name="inPackage" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetPackage" type="java.lang.Package"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches classes in the given package. Packages are specific to their
+ classloader, so classes with the same package name may not have the same package at runtime.]]>
+      </doc>
+    </method>
+    <method name="inSubpackage" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetPackageName" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches classes in the given package and its subpackages. Unlike
+ {@link #inPackage(Package) inPackage()}, this matches classes from any classloader.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="returns" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.Method&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="returnType" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches methods with matching return types.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Matcher implementations. Supports matching classes and methods.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.matcher.Matchers -->
+</package>
+<package name="com.google.inject.multibindings">
+  <!-- start class com.google.inject.multibindings.MapBinder -->
+  <class name="MapBinder" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="addBinding" return="com.google.inject.binder.LinkedBindingBuilder&lt;V&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="K"/>
+      <doc>
+      <![CDATA[Returns a binding builder used to add a new entry in the map. Each
+ key must be distinct (and non-null). Bound providers will be evaluated each
+ time the map is injected.
+
+ <p>It is an error to call this method without also calling one of the
+ {@code to} methods on the returned binding builder.
+
+ <p>Scoping elements independently is supported. Use the {@code in} method
+ to specify a binding scope.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An API to bind multiple map entries separately, only to later inject them as
+ a complete map. MapBinder is intended for use in your application's module:
+ <pre><code>
+ public class SnacksModule extends AbstractModule {
+   protected void configure() {
+     MapBinder&lt;String, Snack&gt; mapbinder
+         = MapBinder.newMapBinder(binder(), String.class, Snack.class);
+     mapbinder.addBinding("twix").toInstance(new Twix());
+     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
+     mapbinder.addBinding("skittles").to(Skittles.class);
+   }
+ }</code></pre>
+
+ <p>With this binding, a {@link Map}{@code <String, Snack>} can now be 
+ injected:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Map&lt;String, Snack&gt; snacks) { ... }
+ }</code></pre>
+ 
+ <p>In addition to binding {@code Map<K, V>}, a mapbinder will also bind
+ {@code Map<K, Provider<V>>} for lazy value provision:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Map&lt;String, Provider&lt;Snack&gt;&gt; snackProviders) { ... }
+ }</code></pre>
+
+ <p>Creating mapbindings from different modules is supported. For example, it
+ is okay to have both {@code CandyModule} and {@code ChipsModule} both
+ create their own {@code MapBinder<String, Snack>}, and to each contribute 
+ bindings to the snacks map. When that map is injected, it will contain 
+ entries from both modules.
+
+ <p>Values are resolved at map injection time. If a value is bound to a
+ provider, that provider's get method will be called each time the map is
+ injected (unless the binding is also scoped, or a map of providers is injected).
+
+ <p>Annotations are used to create different maps of the same key/value
+ type. Each distinct annotation gets its own independent map.
+
+ <p><strong>Keys must be distinct.</strong> If the same key is bound more than
+ once, map injection will fail.
+
+ <p><strong>Keys must be non-null.</strong> {@code addBinding(null)} will 
+ throw an unchecked exception.
+
+ <p><strong>Values must be non-null to use map injection.</strong> If any
+ value is null, map injection will fail (although injecting a map of providers
+ will not).
+
+ @author dpb@google.com (David P. Baker)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.multibindings.MapBinder -->
+  <!-- start class com.google.inject.multibindings.Multibinder -->
+  <class name="Multibinder" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="addBinding" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a binding builder used to add a new element in the set. Each
+ bound element must have a distinct value. Bound providers will be
+ evaluated each time the set is injected.
+
+ <p>It is an error to call this method without also calling one of the
+ {@code to} methods on the returned binding builder.
+
+ <p>Scoping elements independently is supported. Use the {@code in} method
+ to specify a binding scope.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An API to bind multiple values separately, only to later inject them as a
+ complete collection. Multibinder is intended for use in your application's
+ module:
+ <pre><code>
+ public class SnacksModule extends AbstractModule {
+   protected void configure() {
+     Multibinder&lt;Snack&gt; multibinder
+         = Multibinder.newSetBinder(binder(), Snack.class);
+     multibinder.addBinding().toInstance(new Twix());
+     multibinder.addBinding().toProvider(SnickersProvider.class);
+     multibinder.addBinding().to(Skittles.class);
+   }
+ }</code></pre>
+
+ <p>With this binding, a {@link Set}{@code <Snack>} can now be injected:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Set&lt;Snack&gt; snacks) { ... }
+ }</code></pre>
+
+ <p>Create multibindings from different modules is supported. For example, it
+ is okay to have both {@code CandyModule} and {@code ChipsModule} to both
+ create their own {@code Multibinder<Snack>}, and to each contribute bindings
+ to the set of snacks. When that set is injected, it will contain elements
+ from both modules.
+
+ <p>Elements are resolved at set injection time. If an element is bound to a
+ provider, that provider's get method will be called each time the set is
+ injected (unless the binding is also scoped).
+
+ <p>Annotations are be used to create different sets of the same element
+ type. Each distinct annotation gets its own independent collection of
+ elements.
+
+ <p><strong>Elements must be distinct.</strong> If multiple bound elements
+ have the same value, set injection will fail.
+
+ <p><strong>Elements must be non-null.</strong> If any set element is null,
+ set injection will fail.
+
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.multibindings.Multibinder -->
+</package>
+<package name="com.google.inject.name">
+  <!-- start class com.google.inject.name.Named -->
+  <class name="Named"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates named things.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.name.Named -->
+  <!-- start class com.google.inject.name.Names -->
+  <class name="Names" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="named" return="com.google.inject.name.Named"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a {@link Named} annotation with {@code name} as the value.]]>
+      </doc>
+    </method>
+    <method name="bindProperties"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="properties" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+      <doc>
+      <![CDATA[Creates a constant binding to {@code @Named(key)} for each entry in
+ {@code properties}.]]>
+      </doc>
+    </method>
+    <method name="bindProperties"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="properties" type="java.util.Properties"/>
+      <doc>
+      <![CDATA[Creates a constant binding to {@code @Named(key)} for each property. This
+ method binds all properties including those inherited from 
+ {@link Properties#defaults defaults}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Utility methods for use with {@code @}{@link Named}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.name.Names -->
+</package>
+<package name="com.google.inject.servlet">
+  <!-- start class com.google.inject.servlet.GuiceFilter -->
+  <class name="GuiceFilter" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceFilter"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="doFilter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletRequest" type="ServletRequest"/>
+      <param name="servletResponse" type="ServletResponse"/>
+      <param name="filterChain" type="FilterChain"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="init"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterConfig" type="FilterConfig"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="destroy"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[<p>
+ Apply this filter in web.xml above all other filters (typically), to all requests where you plan
+  to use servlet scopes. This is also needed in order to dispatch requests to injectable filters
+  and servlets:
+  <pre>
+  &lt;filter&gt;
+    &lt;filter-name&gt;guiceFilter&lt;/filter-name&gt;
+    &lt;filter-class&gt;<b>com.google.inject.servlet.GuiceFilter</b>&lt;/filter-class&gt;
+  &lt;/filter&gt;
+
+  &lt;filter-mapping&gt;
+    &lt;filter-name&gt;guiceFilter&lt;/filter-name&gt;
+    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+  &lt;/filter-mapping&gt;
+  </pre>
+
+ This filter must appear before every filter that makes use of Guice injection or servlet
+ scopes functionality. Typically, you will only register this filter in web.xml and register
+ any other filters (and servlets) using a {@link ServletModule}.
+
+ @author crazybob@google.com (Bob Lee)
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.GuiceFilter -->
+  <!-- start class com.google.inject.servlet.GuiceServletContextListener -->
+  <class name="GuiceServletContextListener" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceServletContextListener"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="contextInitialized"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletContextEvent" type="ServletContextEvent"/>
+    </method>
+    <method name="contextDestroyed"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletContextEvent" type="ServletContextEvent"/>
+    </method>
+    <method name="getInjector" return="com.google.inject.Injector"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Override this method to create (or otherwise obtain a reference to) your
+ injector.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[As of Guice 2.0 you can still use (your subclasses of) {@code GuiceServletContextListener}
+ class as a logical place to create and configure your injector. This will ensure the injector
+ is created when the web application is deployed.
+ 
+ @author Kevin Bourrillion (kevinb@google.com)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.GuiceServletContextListener -->
+  <!-- start class com.google.inject.servlet.RequestParameters -->
+  <class name="RequestParameters"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to field or parameters of type {@code Map<String, String[]>}
+ when you want the HTTP request parameter map to be injected.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.RequestParameters -->
+  <!-- start class com.google.inject.servlet.RequestScoped -->
+  <class name="RequestScoped"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want one instance per request.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.RequestScoped -->
+  <!-- start class com.google.inject.servlet.ServletModule -->
+  <class name="ServletModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ServletModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="configureServlets"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[<h3>Servlet Mapping EDSL</h3>
+
+ <p> Part of the EDSL builder language for configuring servlets
+ and filters with guice-servlet. Think of this as an in-code replacement for web.xml.
+ Filters and servlets are configured here using simple java method calls. Here is a typical
+ example of registering a filter when creating your Guice injector:
+
+ <pre>
+   Guice.createInjector(..., new ServletModule() {
+
+     {@literal @}Override
+     protected void configureServlets() {
+       <b>serve("*.html").with(MyServlet.class)</b>
+     }
+   }
+ </pre>
+
+ This registers a servlet (subclass of {@code HttpServlet}) called {@code MyServlet} to service
+ any web pages ending in {@code .html}. You can also use a path-style syntax to register
+ servlets:
+
+ <pre>
+       <b>serve("/my/*").with(MyServlet.class)</b>
+ </pre>
+
+ Every servlet (or filter) is required to be a singleton. If you cannot annotate the class
+ directly, you should add a separate {@code bind(..).in(Singleton.class)} rule elsewhere in
+ your module. Mapping a servlet that is bound under any other scope is an error.
+
+ <p>
+ <h4>Dispatch Order</h4>
+ You are free to register as many servlets and filters as you like this way. They will
+ be compared and dispatched in the order in which the filter methods are called:
+
+ <pre>
+
+   Guice.createInjector(..., new ServletModule() {
+
+     {@literal @}Override
+     protected void configureServlets() {
+       filter("/*").through(MyFilter.class);
+       filter("*.css").through(MyCssFilter.class);
+       // etc..
+
+       serve("*.html").with(MyServlet.class);
+       serve("/my/*").with(MyServlet.class);
+       // etc..
+      }
+    }
+ </pre>
+ This will traverse down the list of rules in lexical order. For example, a url
+  "{@code /my/file.js}" (after it runs through the matching filters) will first
+  be compared against the servlet mapping:
+ 
+ <pre>
+       serve("*.html").with(MyServlet.class);
+ </pre>
+ And failing that, it will descend to the next servlet mapping:
+
+ <pre>
+       serve("/my/*").with(MyServlet.class);
+ </pre>
+
+ Since this rule matches, Guice Servlet will dispatch to {@code MyServlet}. These
+ two mapping rules can also be written in more compact form using varargs syntax:
+
+ <pre>
+       serve(<b>"*.html", "/my/*"</b>).with(MyServlet.class);
+ </pre>
+ 
+ This way you can map several URI patterns to the same servlet. A similar syntax is
+ also available for filter mappings.
+
+ <p>
+ <h4>Regular Expressions</h4>
+ You can also map servlets (or filters) to URIs using regular expressions:
+ <pre>
+    <b>serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)</b>
+ </pre>
+
+ This will map any URI containing the text "ajax" in it to {@code MyAjaxServlet}. Such as:
+ <ul>
+ <li>http://www.google.com/ajax.html</li>
+ <li>http://www.google.com/content/ajax/index</li>
+ <li>http://www.google.com/it/is_totally_ajaxian</li>
+ </ul>
+
+
+ <h3>Initialization Parameters</h3>
+
+ Servlets (and filters) allow you to pass in init params
+ using the {@code <init-param>} tag in web.xml. You can similarly pass in parameters to
+ Servlets and filters registered in Guice-servlet using a {@link java.util.Map} of parameter
+ name/value pairs. For example, to initialize {@code MyServlet} with two parameters
+ ({@code name="Dhanji", site="google.com"}) you could write:
+
+ <pre>
+  Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
+  params.put("name", "Dhanji");
+  params.put("site", "google.com");
+
+  ...
+      serve("/*").with(MyServlet.class, <b>params</b>)
+ </pre>
+
+ <p>
+ <h3>Binding Keys</h3>
+
+ You can also bind keys rather than classes. This lets you hide
+ implementations with package-local visbility and expose them using
+ only a Guice module and an annotation:
+
+ <pre>
+  ...
+      filter("/*").through(<b>Key.get(Filter.class, Fave.class)</b>);
+ </pre>
+
+ Where {@code Filter.class} refers to the Servlet API interface and {@code Fave.class} is a
+ custom binding annotation. Elsewhere (in one of your own modules) you can bind this
+ filter's implementation:
+
+ <pre>
+   bind(Filter.class)<b>.annotatedWith(Fave.class)</b>.to(MyFilterImpl.class);
+ </pre>
+
+ See {@link com.google.inject.Binder} for more information on binding syntax.
+
+ <p>
+ <h3>Multiple Modules</h3>
+
+ It is sometimes useful to capture servlet and filter mappings from multiple different
+ modules. This is essential if you want to package and offer drop-in Guice plugins that
+ provide servlet functionality.
+
+ <p>
+ Guice Servlet allows you to register several instances of {@code ServletModule} to your
+ injector. The order in which these modules are installed determines the dispatch order
+ of filters and the precedence order of servlets. For example, if you had two servlet modules,
+ {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped
+ to the same URI pattern, {@code "/*"}:
+
+ <p>
+ In {@code RpcModule}:
+ <pre>
+     filter("/*").through(RpcFilter.class);
+ </pre>
+
+ In {@code WebServiceModule}:
+ <pre>
+     filter("/*").through(WebServiceFilter.class);
+ </pre>
+
+ Then the order in which these filters are dispatched is determined by the order in which
+ the modules are installed:
+
+ <pre>
+   <b>install(new WebServiceModule());</b>
+   install(new RpcModule());
+ </pre>
+
+ In the case shown above {@code WebServiceFilter} will run first.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="filter" return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="urlPattern" type="java.lang.String"/>
+      <param name="morePatterns" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="filterRegex" return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="regex" type="java.lang.String"/>
+      <param name="regexes" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param regex Any Java-style regular expression.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="serve" return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="urlPattern" type="java.lang.String"/>
+      <param name="morePatterns" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="serveRegex" return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="regex" type="java.lang.String"/>
+      <param name="regexes" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param regex Any Java-style regular expression.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Configures the servlet scopes and creates bindings for the servlet API
+ objects so you can inject the request, response, session, etc.
+
+ <p>
+ You should subclass this module to register servlets and
+ filters in the {@link #configureServlets()} method.
+
+ @author crazybob@google.com (Bob Lee)
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ServletModule -->
+  <!-- start interface com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder -->
+  <interface name="ServletModule.FilterKeyBindingBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;"/>
+    </method>
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;"/>
+    </method>
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="dummyFilterClass" type="java.lang.Class&lt;? extends Filter&gt;"/>
+      <param name="contextParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="dummyFilterClass" type="com.google.inject.Key&lt;? extends Filter&gt;"/>
+      <param name="contextParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link ServletModule#configureServlets()}
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder -->
+  <!-- start interface com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder -->
+  <interface name="ServletModule.ServletKeyBindingBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;"/>
+    </method>
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;"/>
+    </method>
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;"/>
+      <param name="contextParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;"/>
+      <param name="contextParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link ServletModule#configureServlets()}
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder -->
+  <!-- start class com.google.inject.servlet.ServletScopes -->
+  <class name="ServletScopes" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <field name="REQUEST" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[HTTP servlet request scope.]]>
+      </doc>
+    </field>
+    <field name="SESSION" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[HTTP session scope.]]>
+      </doc>
+    </field>
+    <doc>
+    <![CDATA[Servlet scopes.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ServletScopes -->
+  <!-- start class com.google.inject.servlet.SessionScoped -->
+  <class name="SessionScoped"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want one instance per session.
+
+ @see com.google.inject.Scopes#SINGLETON
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.SessionScoped -->
+</package>
+<package name="com.google.inject.spi">
+  <!-- start interface com.google.inject.spi.BindingScopingVisitor -->
+  <interface name="BindingScopingVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visitEagerSingleton" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Visit an eager singleton or single instance. This scope strategy is found on both module and
+ injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visitScope" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[Visit a scope instance. This scope strategy is found on both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visitScopeAnnotation" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Visit a scope annotation. This scope strategy is found only on module bindings. The instance
+ that implements this scope is registered by {@link com.google.inject.Binder#bindScope(Class,
+ Scope) Binder.bindScope()}.]]>
+      </doc>
+    </method>
+    <method name="visitNoScoping" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Visit an unspecified or unscoped strategy. On a module, this strategy indicates that the
+ injector should use scoping annotations to find a scope. On an injector, it indicates that
+ no scope is applied to the binding. An unscoped binding will behave like a scoped one when it
+ is linked to a scoped binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visits each of the strategies used to scope an injection.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.BindingScopingVisitor -->
+  <!-- start interface com.google.inject.spi.BindingTargetVisitor -->
+  <interface name="BindingTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a instance binding. The same instance is returned for every injection. This target is
+ found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a provider instance binding. The provider's {@code get} method is invoked to resolve
+ injections. This target is found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a provider key binding. To resolve injections, the provider key is first resolved, then
+ that provider's {@code get} method is invoked. This target is found in both module and injector
+ bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a linked key binding. The other key's binding is used to resolve injections. This
+ target is found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding to a key exposed from an enclosed private environment. This target is only
+ found in injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit an untargetted binding. This target is found only on module bindings. It indicates
+ that the injector should use its implicit binding strategies to resolve injections.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a constructor binding. To resolve injections, an instance is instantiated by invoking
+ {@code constructor}. This target is found only on injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding created from converting a bound instance to a new type. The source binding
+ has the same binding annotation but a different type. This target is found only on injector
+ bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding to a {@link com.google.inject.Provider} that delegates to the binding for the
+ provided type. This target is found only on injector bindings.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visits each of the strategies used to find an instance to satisfy an injection.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.BindingTargetVisitor -->
+  <!-- start interface com.google.inject.spi.ConstructorBinding -->
+  <interface name="ConstructorBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getConstructor" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the constructor this binding injects.]]>
+      </doc>
+    </method>
+    <method name="getInjectableMembers" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.]]>
+      </doc>
+    </method>
+    <method name="getMethodInterceptors" return="java.util.Map&lt;java.lang.reflect.Method, java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the interceptors applied to each method, in the order that they will be applied.
+
+ @return a possibly empty map]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to the constructor of a concrete clss. To resolve injections, an instance is
+ instantiated by invoking the constructor.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ConstructorBinding -->
+  <!-- start interface com.google.inject.spi.ConvertedConstantBinding -->
+  <interface name="ConvertedConstantBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getValue" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the converted value.]]>
+      </doc>
+    </method>
+    <method name="getSourceKey" return="com.google.inject.Key&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for the source binding. That binding can e retrieved from an injector using
+ {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.]]>
+      </doc>
+    </method>
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a singleton set containing only the converted key.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding created from converting a bound instance to a new type. The source binding has the same
+ binding annotation but a different type.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ConvertedConstantBinding -->
+  <!-- start class com.google.inject.spi.DefaultBindingScopingVisitor -->
+  <class name="DefaultBindingScopingVisitor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;"/>
+    <constructor name="DefaultBindingScopingVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visitEagerSingleton" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="visitScope" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+    </method>
+    <method name="visitScopeAnnotation" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+    </method>
+    <method name="visitNoScoping" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to
+ {@link #visitOther()}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ 
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultBindingScopingVisitor -->
+  <!-- start class com.google.inject.spi.DefaultBindingTargetVisitor -->
+  <class name="DefaultBindingTargetVisitor" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <constructor name="DefaultBindingTargetVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instanceBinding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerInstanceBinding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerKeyBinding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="linkedKeyBinding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="exposedBinding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="untargettedBinding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructorBinding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="convertedConstantBinding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerBinding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to {@link
+ #visitOther(Binding)}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultBindingTargetVisitor -->
+  <!-- start class com.google.inject.spi.DefaultElementVisitor -->
+  <class name="DefaultElementVisitor" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.ElementVisitor&lt;V&gt;"/>
+    <constructor name="DefaultElementVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="element" type="com.google.inject.spi.Element"/>
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorBinding" type="com.google.inject.spi.InterceptorBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeBinding" type="com.google.inject.spi.ScopeBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeConverterBinding" type="com.google.inject.spi.TypeConverterBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerLookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectionRequest" type="com.google.inject.spi.InjectionRequest"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="staticInjectionRequest" type="com.google.inject.spi.StaticInjectionRequest"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="privateElements" type="com.google.inject.spi.PrivateElements"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeListenerBinding"/>
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to
+ {@link #visitOther(Element)}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+
+ @author sberlin@gmail.com (Sam Berlin)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultElementVisitor -->
+  <!-- start class com.google.inject.spi.Dependency -->
+  <class name="Dependency" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="get" return="com.google.inject.spi.Dependency&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new dependency that is not attached to an injection point. The returned dependency is
+ nullable.]]>
+      </doc>
+    </method>
+    <method name="forInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectionPoints" type="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"/>
+      <doc>
+      <![CDATA[Returns the dependencies from the given injection points.]]>
+      </doc>
+    </method>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key to the binding that satisfies this dependency.]]>
+      </doc>
+    </method>
+    <method name="isNullable" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if null is a legal value for this dependency.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoint" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the injection point to which this dependency belongs, or null if this dependency isn't
+ attached to a particular injection point.]]>
+      </doc>
+    </method>
+    <method name="getParameterIndex" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the index of this dependency in the injection point's parameter list, or {@code -1} if
+ this dependency does not belong to a parameter list. Only method and constuctor dependencies
+ are elements in a parameter list.]]>
+      </doc>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[A variable that can be resolved by an injector.
+
+ <p>Use {@link #get} to build a freestanding dependency, or {@link InjectionPoint} to build one
+ that's attached to a constructor, method or field.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Dependency -->
+  <!-- start interface com.google.inject.spi.Element -->
+  <interface name="Element"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns an arbitrary object containing information about the "place" where this element was
+ configured. Used by Guice in the production of descriptive error messages.
+
+ <p>Tools might specially handle types they know about; {@code StackTraceElement} is a good
+ example. Tools should simply call {@code toString()} on the source object if the type is
+ unfamiliar.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Accepts an element visitor. Invokes the visitor method specific to this element's type.
+
+ @param visitor to call back on]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Writes this module element to the given binder (optional operation).
+
+ @param binder to apply configuration element to
+ @throws UnsupportedOperationException if the {@code applyTo} method is not supported by this
+     element.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A core component of a module or injector.
+
+ <p>The elements of a module can be inspected, validated and rewritten. Use {@link
+ Elements#getElements(com.google.inject.Module[]) Elements.getElements()} to read the elements
+ from a module, and {@link Elements#getModule(Iterable) Elements.getModule()} to rewrite them.
+ This can be used for static analysis and generation of Guice modules.
+
+ <p>The elements of an injector can be inspected and exercised. Use {@link
+ com.google.inject.Injector#getBindings Injector.getBindings()} to reflect on Guice injectors.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.Element -->
+  <!-- start class com.google.inject.spi.Elements -->
+  <class name="Elements" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Elements"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getModule" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elements" type="java.lang.Iterable&lt;? extends com.google.inject.spi.Element&gt;"/>
+      <doc>
+      <![CDATA[Returns the module composed of {@code elements}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Exposes elements of a module so they can be inspected, validated or {@link
+ Element#applyTo(Binder) rewritten}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Elements -->
+  <!-- start interface com.google.inject.spi.ElementVisitor -->
+  <interface name="ElementVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a mapping from a key (type and optional annotation) to the strategy for getting
+ instances of the type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InterceptorBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of interceptors for matching methods of matching classes.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ScopeBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of a scope annotation with the scope that implements it.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeConverterBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of type converters for matching target types.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="request" type="com.google.inject.spi.InjectionRequest"/>
+      <doc>
+      <![CDATA[Visit a request to inject the instance fields and methods of an instance.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="request" type="com.google.inject.spi.StaticInjectionRequest"/>
+      <doc>
+      <![CDATA[Visit a request to inject the static fields and methods of type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a lookup of the provider for a type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a lookup of the members injector.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Visit an error message and the context in which it occured.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elements" type="com.google.inject.spi.PrivateElements"/>
+      <doc>
+      <![CDATA[Visit a collection of configuration elements for a {@linkplain com.google.inject.PrivateBinder
+ private binder}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeListenerBinding"/>
+      <doc>
+      <![CDATA[Visit an injectable type listener binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visit elements.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ 
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ElementVisitor -->
+  <!-- start interface com.google.inject.spi.ExposedBinding -->
+  <interface name="ExposedBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getPrivateElements" return="com.google.inject.spi.PrivateElements"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the enclosed environment that holds the original binding.]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Unsupported. Always throws {@link UnsupportedOperationException}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a key exposed from an enclosed private environment.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ExposedBinding -->
+  <!-- start interface com.google.inject.spi.HasDependencies -->
+  <interface name="HasDependencies"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the known dependencies for this type. If this has dependencies whose values are not
+ known statically, a dependency for the {@link com.google.inject.Injector Injector} will be
+ included in the returned set.
+ 
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Implemented by {@link com.google.inject.Binding bindings}, {@link com.google.inject.Provider
+ providers} and instances that expose their dependencies explicitly.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.HasDependencies -->
+  <!-- start interface com.google.inject.spi.InjectionListener -->
+  <interface name="InjectionListener"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="afterInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectee" type="I"/>
+      <doc>
+      <![CDATA[Invoked by Guice after it injects the fields and methods of instance.
+
+ @param injectee instance that Guice injected dependencies into]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Listens for injections into instances of type {@code I}. Useful for performing further
+ injections, post-injection initialization, and more.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.InjectionListener -->
+  <!-- start class com.google.inject.spi.InjectionPoint -->
+  <class name="InjectionPoint" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="getMember" return="java.lang.reflect.Member"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the injected constructor, field, or method.]]>
+      </doc>
+    </method>
+    <method name="getDependencies" return="java.util.List&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the dependencies for this injection point. If the injection point is for a method or
+ constructor, the dependencies will correspond to that member's parameters. Field injection
+ points always have a single dependency for the field itself.
+
+ @return a possibly-empty list]]>
+      </doc>
+    </method>
+    <method name="isOptional" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if this injection point shall be skipped if the injector cannot resolve bindings
+ for all required dependencies. Both explicit bindings (as specified in a module), and implicit
+ bindings ({@literal @}{@link com.google.inject.ImplementedBy ImplementedBy}, default
+ constructors etc.) may be used to satisfy optional injection points.]]>
+      </doc>
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="forConstructorOf" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the injectable constructor of {@code type}.
+
+ @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
+     or a no-arguments constructor that is not private.
+ @throws ConfigurationException if there is no injectable constructor, more than one injectable
+     constructor, or if parameters of the injectable constructor are malformed, such as a
+     parameter with multiple binding annotations.]]>
+      </doc>
+    </method>
+    <method name="forConstructorOf" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the injectable constructor of {@code type}.
+
+ @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
+     or a no-arguments constructor that is not private.
+ @throws ConfigurationException if there is no injectable constructor, more than one injectable
+     constructor, or if parameters of the injectable constructor are malformed, such as a
+     parameter with multiple binding annotations.]]>
+      </doc>
+    </method>
+    <method name="forStaticMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral"/>
+      <doc>
+      <![CDATA[Returns all static method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forStaticMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all static method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forInstanceMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forInstanceMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A constructor, field or method that can receive injections. Typically this is a member with the
+ {@literal @}{@link Inject} annotation. For non-private, no argument constructors, the member may
+ omit the annotation. 
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InjectionPoint -->
+  <!-- start class com.google.inject.spi.InjectionRequest -->
+  <class name="InjectionRequest" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="InjectionRequest" type="java.lang.Object, com.google.inject.TypeLiteral&lt;T&gt;, T"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="ConfigurationException" type="com.google.inject.ConfigurationException"/>
+      <doc>
+      <![CDATA[Returns the instance methods and fields of {@code instance} that will be injected to fulfill
+ this request.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on the class of {@code
+      instance}, such as a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="R"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;R&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[A request to inject the instance fields and methods of an instance. Requests are created
+ explicitly in a module using {@link com.google.inject.Binder#requestInjection(Object)
+ requestInjection()} statements:
+ <pre>
+     requestInjection(serviceInstance);</pre>
+
+ @author mikeward@google.com (Mike Ward)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InjectionRequest -->
+  <!-- start interface com.google.inject.spi.InstanceBinding -->
+  <interface name="InstanceBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the user-supplied instance.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the field and method injection points of the instance, injected at injector-creation
+ time only.
+
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a single instance. The same instance is returned for every injection.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.InstanceBinding -->
+  <!-- start class com.google.inject.spi.InterceptorBinding -->
+  <class name="InterceptorBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassMatcher" return="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getMethodMatcher" return="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInterceptors" return="java.util.List&lt;MethodInterceptor&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Registration of interceptors for matching methods of matching classes. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#bindInterceptor(
+ Matcher, Matcher, MethodInterceptor[]) bindInterceptor()} statements:
+ <pre>
+     bindInterceptor(Matchers.subclassesOf(MyAction.class),
+         Matchers.annotatedWith(Transactional.class),
+         new MyTransactionInterceptor());</pre>
+
+ or from an injectable type listener using {@link TypeEncounter#bindInterceptor(Matcher,
+ org.aopalliance.intercept.MethodInterceptor[]) TypeEncounter.bindInterceptor()}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InterceptorBinding -->
+  <!-- start interface com.google.inject.spi.LinkedKeyBinding -->
+  <interface name="LinkedKeyBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getLinkedKey" return="com.google.inject.Key&lt;? extends T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the linked key used to resolve injections. That binding can be retrieved from an
+ injector using {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a linked key. The other key's binding is used to resolve injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.LinkedKeyBinding -->
+  <!-- start class com.google.inject.spi.MembersInjectorLookup -->
+  <class name="MembersInjectorLookup" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="MembersInjectorLookup" type="java.lang.Object, com.google.inject.TypeLiteral&lt;T&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the type containing the members to be injected.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="initializeDelegate"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="delegate" type="com.google.inject.MembersInjector&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Sets the actual members injector.
+
+ @throws IllegalStateException if the delegate is already set]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="getDelegate" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the delegate members injector, or {@code null} if it has not yet been initialized.
+ The delegate will be initialized when this element is processed, or otherwise used to create
+ an injector.]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the looked up members injector. The result is not valid until this lookup has been
+ initialized, which usually happens when the injector is created. The members injector will
+ throw an {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A lookup of the members injector for a type. Lookups are created explicitly in a module using
+ {@link com.google.inject.Binder#getMembersInjector(Class) getMembersInjector()} statements:
+ <pre>
+     MembersInjector&lt;PaymentService&gt; membersInjector
+         = getMembersInjector(PaymentService.class);</pre>
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.MembersInjectorLookup -->
+  <!-- start class com.google.inject.spi.Message -->
+  <class name="Message" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.io.Serializable"/>
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="Message" type="java.util.List&lt;java.lang.Object&gt;, java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </constructor>
+    <constructor name="Message" type="java.lang.Object, java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="Message" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getSources" return="java.util.List&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the error message text.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <method name="getCause" return="java.lang.Throwable"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the throwable that caused this message, or {@code null} if this
+ message was not caused by a throwable.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An error message and the context in which it occured. Messages are usually created internally by
+ Guice and its extensions. Messages can be created explicitly in a module using {@link
+ com.google.inject.Binder#addError(Throwable) addError()} statements:
+ <pre>
+     try {
+       bindPropertiesFromFile();
+     } catch (IOException e) {
+       addError(e);
+     }</pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Message -->
+  <!-- start interface com.google.inject.spi.PrivateElements -->
+  <interface name="PrivateElements"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the configuration information in this private environment.]]>
+      </doc>
+    </method>
+    <method name="getInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the child injector that hosts these private elements, or null if the elements haven't
+ been used to create an injector.]]>
+      </doc>
+    </method>
+    <method name="getExposedKeys" return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the unique exposed keys for these private elements.]]>
+      </doc>
+    </method>
+    <method name="getExposedSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns an arbitrary object containing information about the "place" where this key was
+ exposed. Used by Guice in the production of descriptive error messages.
+
+ <p>Tools might specially handle types they know about; {@code StackTraceElement} is a good
+ example. Tools should simply call {@code toString()} on the source object if the type is
+ unfamiliar.
+
+ @param key one of the keys exposed by this module.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A private collection of elements that are hidden from the enclosing injector or module by
+ default. See {@link com.google.inject.PrivateModule PrivateModule} for details.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.PrivateElements -->
+  <!-- start interface com.google.inject.spi.ProviderBinding -->
+  <interface name="ProviderBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getProvidedKey" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key whose binding is used to {@link Provider#get provide instances}. That binding
+ can be retrieved from an injector using {@link com.google.inject.Injector#getBinding(Key)
+ Injector.getBinding(providedKey)}]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a {@link Provider} that delegates to the binding for the provided type. This binding
+ is used whenever a {@code Provider<T>} is injected (as opposed to injecting {@code T} directly).
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderBinding -->
+  <!-- start interface com.google.inject.spi.ProviderInstanceBinding -->
+  <interface name="ProviderInstanceBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getProviderInstance" return="com.google.inject.Provider&lt;? extends T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the user-supplied, unscoped provider.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the field and method injection points of the provider, injected at injector-creation
+ time only.
+
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a provider instance. The provider's {@code get} method is invoked to resolve
+ injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderInstanceBinding -->
+  <!-- start interface com.google.inject.spi.ProviderKeyBinding -->
+  <interface name="ProviderKeyBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getProviderKey" return="com.google.inject.Key&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key used to resolve the provider's binding. That binding can be retrieved from an
+ injector using {@link com.google.inject.Injector#getBinding(Key)
+ Injector.getBinding(providerKey)}]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a provider key. To resolve injections, the provider key is first resolved, then that
+ provider's {@code get} method is invoked.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderKeyBinding -->
+  <!-- start class com.google.inject.spi.ProviderLookup -->
+  <class name="ProviderLookup" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="ProviderLookup" type="java.lang.Object, com.google.inject.Key&lt;T&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="initializeDelegate"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="delegate" type="com.google.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Sets the actual provider.
+
+ @throws IllegalStateException if the delegate is already set]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="getDelegate" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the delegate provider, or {@code null} if it has not yet been initialized. The delegate
+ will be initialized when this element is processed, or otherwise used to create an injector.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the looked up provider. The result is not valid until this lookup has been initialized,
+ which usually happens when the injector is created. The provider will throw an {@code
+ IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A lookup of the provider for a type. Lookups are created explicitly in a module using
+ {@link com.google.inject.Binder#getProvider(Class) getProvider()} statements:
+ <pre>
+     Provider&lt;PaymentService&gt; paymentServiceProvider
+         = getProvider(PaymentService.class);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ProviderLookup -->
+  <!-- start interface com.google.inject.spi.ProviderWithDependencies -->
+  <interface name="ProviderWithDependencies"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Provider&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <doc>
+    <![CDATA[A provider with dependencies on other injected types. If a {@link Provider} has dependencies that
+ aren't specified in injections, this interface should be used to expose all dependencies.
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderWithDependencies -->
+  <!-- start class com.google.inject.spi.ScopeBinding -->
+  <class name="ScopeBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getAnnotationType" return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getScope" return="com.google.inject.Scope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Registration of a scope annotation with the scope that implements it. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#bindScope(Class, Scope) bindScope()}
+ statements:
+ <pre>
+     Scope recordScope = new RecordScope();
+     bindScope(RecordScoped.class, new RecordScope());</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ScopeBinding -->
+  <!-- start class com.google.inject.spi.StaticInjectionRequest -->
+  <class name="StaticInjectionRequest" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="java.lang.Class&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="ConfigurationException" type="com.google.inject.ConfigurationException"/>
+      <doc>
+      <![CDATA[Returns the static methods and fields of {@code type} that will be injected to fulfill this
+ request.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to inject the static fields and methods of a type. Requests are created
+ explicitly in a module using {@link com.google.inject.Binder#requestStaticInjection(Class[])
+ requestStaticInjection()} statements:
+ <pre>
+     requestStaticInjection(MyLegacyService.class);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.StaticInjectionRequest -->
+  <!-- start interface com.google.inject.spi.TypeConverter -->
+  <interface name="TypeConverter"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="convert" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.String"/>
+      <param name="toType" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Converts a string value. Throws an exception if a conversion error occurs.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Converts constant string values to a different type.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeConverter -->
+  <!-- start class com.google.inject.spi.TypeConverterBinding -->
+  <class name="TypeConverterBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTypeMatcher" return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTypeConverter" return="com.google.inject.spi.TypeConverter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Registration of type converters for matching target types. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#convertToTypes(Matcher,
+ TypeConverter) convertToTypes()} statements:
+ <pre>
+     convertToTypes(Matchers.only(DateTime.class), new DateTimeConverter());</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.TypeConverterBinding -->
+  <!-- start interface com.google.inject.spi.TypeEncounter -->
+  <interface name="TypeEncounter"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[Records an error message for type {@code I} which will be presented to the user at a later
+ time. Unlike throwing an exception, this enable us to continue configuring the Injector and
+ discover more errors. Uses {@link String#format(String, Object[])} to insert the arguments
+ into the message.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[Records an exception for type {@code I}, the full details of which will be logged, and the
+ message of which will be presented to the user at a later time. If your type listener calls
+ something that you worry may fail, you should catch the exception and pass it to this method.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Records an error message to be presented to the user at a later time.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key. The returned
+ provider will not be valid until the injector has been created. The provider will throw an
+ {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection type. The returned
+ provider will not be valid until the injetor has been created. The provider will throw an
+ {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ injector has been created. The members injector will throw an {@code IllegalStateException}
+ if you try to use it beforehand.
+
+ @param typeLiteral type to get members injector for]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ injector has been created. The members injector will throw an {@code IllegalStateException}
+ if you try to use it beforehand.
+
+ @param type type to get members injector for]]>
+      </doc>
+    </method>
+    <method name="register"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="membersInjector" type="com.google.inject.MembersInjector&lt;? super I&gt;"/>
+      <doc>
+      <![CDATA[Registers a members injector for type {@code I}. Guice will use the members injector after its
+ performed its own injections on an instance of {@code I}.]]>
+      </doc>
+    </method>
+    <method name="register"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="listener" type="com.google.inject.spi.InjectionListener&lt;? super I&gt;"/>
+      <doc>
+      <![CDATA[Registers an injection listener for type {@code I}. Guice will notify the listener after all
+ injections have been performed on an instance of {@code I}.]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[Binds method interceptor[s] to methods matched in type {@code I} and its supertypes. A
+ method is eligible for interception if:
+
+ <ul>
+  <li>Guice created the instance the method is on</li>
+  <li>Neither the enclosing type nor the method is final</li>
+  <li>And the method is package-private or more accessible</li>
+ </ul>
+
+ @param methodMatcher matches methods the interceptor should apply to. For
+     example: {@code annotatedWith(Transactional.class)}.
+ @param interceptors to bind]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Context of an injectable type encounter. Enables reporting errors, registering injection
+ listeners and binding method interceptors for injectable type {@code I}. It is an error to use
+ an encounter after the {@link TypeListener#hear(TypeLiteral, TypeEncounter) hear()} method has
+ returned.
+
+ @param <I> the injectable type encountered
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeEncounter -->
+  <!-- start interface com.google.inject.spi.TypeListener -->
+  <interface name="TypeListener"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="hear"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;I&gt;"/>
+      <param name="encounter" type="com.google.inject.spi.TypeEncounter&lt;I&gt;"/>
+      <doc>
+      <![CDATA[Invoked when Guice encounters a new type eligible for constructor or members injection.
+ Called during injector creation (or afterwords if Guice encounters a type at run time and
+ creates a JIT binding).
+
+ @param type encountered by Guice
+ @param encounter context of this encounter, enables reporting errors, registering injection
+     listeners and binding method interceptors for {@code type}.
+
+ @param <I> the injectable type]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Listens for Guice to encounter injectable types. If a given type has its constructor injected in
+ one situation but only its methods and fields injected in another, Guice will notify this
+ listener once.
+
+ <p>Useful for extra type checking, {@linkplain TypeEncounter#register(InjectionListener)
+ registering injection listeners}, and {@linkplain TypeEncounter#bindInterceptor(
+ com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])
+ binding method interceptors}.
+ 
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeListener -->
+  <!-- start class com.google.inject.spi.TypeListenerBinding -->
+  <class name="TypeListenerBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getListener" return="com.google.inject.spi.TypeListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the registered listener.]]>
+      </doc>
+    </method>
+    <method name="getTypeMatcher" return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the type matcher which chooses which types the listener should be notified of.]]>
+      </doc>
+    </method>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Binds types (picked using a Matcher) to an type listener. Registrations are created explicitly in
+ a module using {@link com.google.inject.Binder#bindListener(Matcher, TypeListener)} statements:
+
+ <pre>
+     register(only(new TypeLiteral&lt;PaymentService&lt;CreditCard>>() {}), listener);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.TypeListenerBinding -->
+  <!-- start interface com.google.inject.spi.UntargettedBinding -->
+  <interface name="UntargettedBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <doc>
+    <![CDATA[An untargetted binding. This binding indicates that the injector should use its implicit binding
+ strategies to resolve injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.UntargettedBinding -->
+</package>
+<package name="com.google.inject.spring">
+  <!-- start class com.google.inject.spring.SpringIntegration -->
+  <class name="SpringIntegration" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="fromSpring" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a provider which looks up objects from Spring using the given name.
+ Expects a binding to {@link
+ org.springframework.beans.factory.BeanFactory}. Example usage:
+
+ <pre>
+ bind(DataSource.class)
+   .toProvider(fromSpring(DataSource.class, "dataSource"));
+ </pre>]]>
+      </doc>
+    </method>
+    <method name="bindAll"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="beanFactory" type="ListableBeanFactory"/>
+      <doc>
+      <![CDATA[Binds all Spring beans from the given factory by name. For a Spring bean
+ named "foo", this method creates a binding to the bean's type and
+ {@code @Named("foo")}.
+
+ @see com.google.inject.name.Named
+ @see com.google.inject.name.Names#named(String)]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Integrates Guice with Spring.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spring.SpringIntegration -->
+</package>
+<package name="com.google.inject.struts2">
+  <!-- start class com.google.inject.struts2.GuiceObjectFactory -->
+  <class name="GuiceObjectFactory" extends="ObjectFactory"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceObjectFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="isNoArgConstructorRequired" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassInstance" return="java.lang.Class"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException"/>
+    </method>
+    <method name="buildBean" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class"/>
+      <param name="extraContext" type="java.util.Map"/>
+    </method>
+    <method name="buildInterceptor" return="Interceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorConfig" type="InterceptorConfig"/>
+      <param name="interceptorRefParams" type="java.util.Map"/>
+      <exception name="ConfigurationException" type="ConfigurationException"/>
+    </method>
+  </class>
+  <!-- end class com.google.inject.struts2.GuiceObjectFactory -->
+</package>
+<package name="com.google.inject.throwingproviders">
+  <!-- start interface com.google.inject.throwingproviders.ThrowingProvider -->
+  <interface name="ThrowingProvider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="get" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="Exception" type="java.lang.Exception"/>
+    </method>
+    <doc>
+    <![CDATA[Alternative to the Guice {@link com.google.inject.Provider} that throws
+ a checked Exception. Users may not inject {@code T} directly.
+
+ <p>This interface must be extended to use application-specific exception types.
+ Such subinterfaces may not define new methods:
+ <pre>
+ public interface RemoteProvider&lt;T&gt; extends ThrowingProvider&lt;T, RemoteException&gt; { }
+ </pre>
+
+ <p>When this type is bound using {@link ThrowingProviderBinder}, the value returned
+ or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get}
+ will invoked at most once within each scope.
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.throwingproviders.ThrowingProvider -->
+  <!-- start class com.google.inject.throwingproviders.ThrowingProviderBinder -->
+  <class name="ThrowingProviderBinder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="create" return="com.google.inject.throwingproviders.ThrowingProviderBinder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="bind" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interfaceType" type="java.lang.Class&lt;P&gt;"/>
+      <param name="valueType" type="java.lang.reflect.Type"/>
+    </method>
+    <doc>
+    <![CDATA[<p>Builds a binding for a {@link ThrowingProvider} using a fluent API:
+ <pre><code>ThrowingProviderBinder.create(binder())
+    .bind(RemoteProvider.class, Customer.class)
+    .to(RemoteCustomerProvider.class)
+    .in(RequestScope.class);
+ </code></pre>
+ 
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.ThrowingProviderBinder -->
+  <!-- start class com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder -->
+  <class name="ThrowingProviderBinder.SecondaryBinder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ThrowingProviderBinder.SecondaryBinder" type="java.lang.Class&lt;P&gt;, java.lang.reflect.Type"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="annotatedWith" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="target" type="P extends com.google.inject.throwingproviders.ThrowingProvider"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetType" type="java.lang.Class&lt;? extends P&gt;"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetKey" type="com.google.inject.Key&lt;? extends P&gt;"/>
+    </method>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder -->
+</package>
+<package name="com.google.inject.tools.jmx">
+  <!-- start interface com.google.inject.tools.jmx.ManagedBindingMBean -->
+  <interface name="ManagedBindingMBean"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSource" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the source of this binding.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the provider to which this binding is bound.]]>
+      </doc>
+    </method>
+    <method name="getKey" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the binding key.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[JMX interface to bindings.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.tools.jmx.ManagedBindingMBean -->
+  <!-- start class com.google.inject.tools.jmx.Manager -->
+  <class name="Manager" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Manager"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="manage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="domain" type="java.lang.String"/>
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Registers all the bindings of an Injector with the platform MBean server.
+ Consider using the name of your root {@link Module} class as the domain.]]>
+      </doc>
+    </method>
+    <method name="manage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="server" type="javax.management.MBeanServer"/>
+      <param name="domain" type="java.lang.String"/>
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Registers all the bindings of an Injector with the given MBean server.
+ Consider using the name of your root {@link Module} class as the domain.]]>
+      </doc>
+    </method>
+    <method name="main"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="args" type="java.lang.String[]"/>
+      <exception name="Exception" type="java.lang.Exception"/>
+      <doc>
+      <![CDATA[Run with no arguments for usage instructions.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Provides a JMX interface to Guice.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.tools.jmx.Manager -->
+</package>
+<package name="com.google.inject.util">
+  <!-- start class com.google.inject.util.Modules -->
+  <class name="Modules" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="override" return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a builder that creates a module that overlays override modules over the given
+ modules. If a key is bound in both sets of modules, only the binding from the override modules
+ is kept. This can be used to replace the bindings of a production module with test bindings:
+ <pre>
+ Module functionalTestModule
+     = Modules.override(new ProductionModule()).with(new TestModule());
+ </pre>
+
+ <p>Prefer to write smaller modules that can be reused and tested without overrides.
+
+ @param modules the modules whose bindings are open to be overridden]]>
+      </doc>
+    </method>
+    <method name="override" return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a builder that creates a module that overlays override modules over the given
+ modules. If a key is bound in both sets of modules, only the binding from the override modules
+ is kept. This can be used to replace the bindings of a production module with test bindings:
+ <pre>
+ Module functionalTestModule
+     = Modules.override(getProductionModules()).with(getTestModules());
+ </pre>
+
+ <p>Prefer to write smaller modules that can be reused and tested without overrides.
+
+ @param modules the modules whose bindings are open to be overridden]]>
+      </doc>
+    </method>
+    <method name="combine" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a new module that installs all of {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="combine" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a new module that installs all of {@code modules}.]]>
+      </doc>
+    </method>
+    <field name="EMPTY_MODULE" type="com.google.inject.Module"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+    </field>
+    <doc>
+    <![CDATA[Static utility methods for creating and working with instances of {@link Module}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Modules -->
+  <!-- start interface com.google.inject.util.Modules.OverriddenModuleBuilder -->
+  <interface name="Modules.OverriddenModuleBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="with" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="overrides" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+      </doc>
+    </method>
+    <method name="with" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="overrides" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.util.Modules.OverriddenModuleBuilder -->
+  <!-- start class com.google.inject.util.Providers -->
+  <class name="Providers" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="of" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Returns a provider which always provides {@code instance}.  This should not
+ be necessary to use in your application, but is helpful for several types
+ of unit tests.
+
+ @param instance the instance that should always be provided.  This is also
+     permitted to be null, to enable aggressive testing, although in real
+     life a Guice-supplied Provider will never return null.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Static utility methods for creating and working with instances of
+ {@link Provider}.
+
+ @author Kevin Bourrillion (kevinb9n@gmail.com)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Providers -->
+  <!-- start class com.google.inject.util.Types -->
+  <class name="Types" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="newParameterizedType" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="rawType" type="java.lang.reflect.Type"/>
+      <param name="typeArguments" type="java.lang.reflect.Type[]"/>
+      <doc>
+      <![CDATA[Returns a new parameterized type, applying {@code typeArguments} to
+ {@code rawType}. The returned type does not have an owner type.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="newParameterizedTypeWithOwner" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="ownerType" type="java.lang.reflect.Type"/>
+      <param name="rawType" type="java.lang.reflect.Type"/>
+      <param name="typeArguments" type="java.lang.reflect.Type[]"/>
+      <doc>
+      <![CDATA[Returns a new parameterized type, applying {@code typeArguments} to
+ {@code rawType} and enclosed by {@code ownerType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="arrayOf" return="java.lang.reflect.GenericArrayType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="componentType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns an array type whose elements are all instances of
+ {@code componentType}.
+
+ @return a {@link java.io.Serializable serializable} generic array type.]]>
+      </doc>
+    </method>
+    <method name="subtypeOf" return="java.lang.reflect.WildcardType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bound" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type that represents an unknown type that extends {@code bound}.
+ For example, if {@code bound} is {@code CharSequence.class}, this returns
+ {@code ? extends CharSequence}. If {@code bound} is {@code Object.class},
+ this returns {@code ?}, which is shorthand for {@code ? extends Object}.]]>
+      </doc>
+    </method>
+    <method name="supertypeOf" return="java.lang.reflect.WildcardType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bound" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type that represents an unknown supertype of {@code bound}. For
+ example, if {@code bound} is {@code String.class}, this returns {@code ?
+ super String}.]]>
+      </doc>
+    </method>
+    <method name="listOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elementType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link List} whose elements are of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="setOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elementType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Set} whose elements are of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="mapOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="keyType" type="java.lang.reflect.Type"/>
+      <param name="valueType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Map} whose keys are of type
+ {@code keyType} and whose values are of type {@code valueType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="providerOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providedType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Provider} that provides elements of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Static methods for working with types.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Types -->
+</package>
+
+</api>
diff --git a/latest-api-diffs/3.0.xml b/latest-api-diffs/3.0.xml
new file mode 100644
index 0000000..021ac8f
--- /dev/null
+++ b/latest-api-diffs/3.0.xml
@@ -0,0 +1,10273 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<!-- on Thu Mar 24 21:41:19 EDT 2011 -->
+
+<api
+  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+  xsi:noNamespaceSchemaLocation='api.xsd'
+  name="3.0"
+  jdversion="1.1.1">
+
+<!--  Command line arguments =  -doclet jdiff.JDiff -docletpath C:\Documents and Settings\Sam Berlin\workspace\guice\lib\build\jdiff\jdiff.jar;C:\Documents and Settings\Sam Berlin\workspace\guice\lib\build\jdiff\xerces.jar -classpath C:\Documents and Settings\Sam Berlin\workspace\guice\lib\javax.inject.jar;C:\Documents and Settings\Sam Berlin\workspace\guice\lib\aopalliance.jar -apidir build/docs/latest-api-diffs -apiname 3.0 -->
+<package name="com.google.inject">
+  <!-- start class com.google.inject.AbstractModule -->
+  <class name="AbstractModule" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Module"/>
+    <constructor name="AbstractModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="true"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="builder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="configure"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Configures a {@link Binder} via the exposed methods.]]>
+      </doc>
+    </method>
+    <method name="binder" return="com.google.inject.Binder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets direct access to the underlying {@code Binder}.]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[@see Binder#bindScope(Class, Scope)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Key)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Class)]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#bindConstant()]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[@see Binder#install(Module)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[@see Binder#addError(String, Object[])]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Throwable)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Message)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[@see Binder#requestInjection(Object)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[@see Binder#requestStaticInjection(Class[])]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindInterceptor(com.google.inject.matcher.Matcher,
+  com.google.inject.matcher.Matcher,
+  org.aopalliance.intercept.MethodInterceptor[])]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Adds a dependency from this module to {@code key}. When the injector is
+ created, Guice will report an error if {@code key} cannot be injected.
+ Note that this requirement may be satisfied by implicit binding, such as
+ a public no-arguments constructor.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Adds a dependency from this module to {@code type}. When the injector is
+ created, Guice will report an error if {@code type} cannot be injected.
+ Note that this requirement may be satisfied by implicit binding, such as
+ a public no-arguments constructor.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Key)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Class)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[@see Binder#convertToTypes
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#currentStage() 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(Class)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(TypeLiteral)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[@see Binder#bindListener(com.google.inject.matcher.Matcher,
+  com.google.inject.spi.TypeListener)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A support class for {@link Module}s which reduces repetition and results in
+ a more readable configuration. Simply extend this class, implement {@link
+ #configure()}, and call the inherited methods which mirror those found in
+ {@link Binder}. For example:
+
+ <pre>
+ public class MyModule extends AbstractModule {
+   protected void configure() {
+     bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
+     bind(CreditCardPaymentService.class);
+     bind(PaymentService.class).to(CreditCardPaymentService.class);
+     bindConstant().annotatedWith(Names.named("port")).to(8080);
+   }
+ }
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.AbstractModule -->
+  <!-- start interface com.google.inject.Binder -->
+  <interface name="Binder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[Binds method interceptor[s] to methods matched by class and method matchers. A method is
+ eligible for interception if:
+
+ <ul>
+  <li>Guice created the instance the method is on</li>
+  <li>Neither the enclosing type nor the method is final</li>
+  <li>And the method is package-private, protected, or public</li>
+ </ul>
+
+ @param classMatcher matches classes the interceptor should apply to. For
+     example: {@code only(Runnable.class)}.
+ @param methodMatcher matches methods the interceptor should apply to. For
+     example: {@code annotatedWith(Transactional.class)}.
+ @param interceptors to bind]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[Binds a scope to an annotation.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject instance fields
+ and methods of the given object.
+
+ @param type of instance
+ @param instance for which members will be injected
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject instance fields
+ and methods of the given object.
+
+ @param instance for which members will be injected
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject static fields
+ and methods in the given classes.
+
+ @param types for which static members will be injected]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[Uses the given module to configure more bindings.]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the current stage.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[Records an error message which will be presented to the user at a later
+ time. Unlike throwing an exception, this enable us to continue
+ configuring the Injector and discover more errors. Uses {@link
+ String#format(String, Object[])} to insert the arguments into the
+ message.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[Records an exception, the full details of which will be logged, and the
+ message of which will be presented to the user at a later
+ time. If your Module calls something that you worry may fail, you should
+ catch the exception and pass it into this.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Records an error message to be presented to the user at a later time.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key.
+ The returned provider will not be valid until the {@link Injector} has been
+ created. The provider will throw an {@code IllegalStateException} if you
+ try to use it beforehand.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection type.
+ The returned provider will not be valid until the {@link Injector} has been
+ created. The provider will throw an {@code IllegalStateException} if you
+ try to use it beforehand.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ {@link Injector} has been created. The members injector will throw an {@code
+ IllegalStateException} if you try to use it beforehand.
+
+ @param typeLiteral type to get members injector for
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ {@link Injector} has been created. The members injector will throw an {@code
+ IllegalStateException} if you try to use it beforehand.
+
+ @param type type to get members injector for
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[Binds a type converter. The injector will use the given converter to
+ convert string constants to matching types as needed.
+
+ @param typeMatcher matches types the converter can handle
+ @param converter converts values
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[Registers a listener for injectable types. Guice will notify the listener when it encounters
+ injectable types matched by the given type matcher.
+
+ @param typeMatcher that matches injectable types the listener should be notified of
+ @param listener for injectable types matched by typeMatcher
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="withSource" return="com.google.inject.Binder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a binder that uses {@code source} as the reference location for
+ configuration errors. This is typically a {@link StackTraceElement}
+ for {@code .java} source but it could any binding source, such as the
+ path to a {@code .properties} file.
+
+ @param source any object representing the source location and has a
+     concise {@link Object#toString() toString()} value
+ @return a binder that shares its configuration with this binder
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="skipSources" return="com.google.inject.Binder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classesToSkip" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[Returns a binder that skips {@code classesToSkip} when identify the
+ calling code. The caller's {@link StackTraceElement} is used to locate
+ the source of configuration errors.
+
+ @param classesToSkip library classes that create bindings on behalf of
+      their clients.
+ @return a binder that shares its configuration with this binder.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="newPrivateBinder" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a new private child environment for bindings and other configuration. The returned
+ binder can be used to add and configuration information in this environment. See {@link
+ PrivateModule} for details.
+
+ @return a binder that inherits configuration from this binder. Only exposed configuration on
+      the returned binder will be visible to this binder.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requireExplicitBindings"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Instructs the Injector that bindings must be listed in a Module in order to
+ be injected. Classes that are not explicitly bound in a module cannot be
+ injected. Bindings created through a linked binding (
+ <code>bind(Foo.class).to(FooImpl.class)</code>) are allowed, but the
+ implicit binding (<code>FooImpl</code>) cannot be directly injected unless
+ it is also explicitly bound (<code>bind(FooImpl.class)</code>).
+ <p>
+ Tools can still retrieve bindings for implicit bindings (bindings created
+ through a linked binding) if explicit bindings are required, however
+ {@link Binding#getProvider} will fail.
+ <p>
+ By default, explicit bindings are not required.
+ <p>
+ If a parent injector requires explicit bindings, then all child injectors
+ (and private modules within that injector) also require explicit bindings.
+ If a parent does not require explicit bindings, a child injector or private
+ module may optionally declare itself as requiring explicit bindings. If it
+ does, the behavior is limited only to that child or any grandchildren. No
+ siblings of the child will require explicit bindings.
+ <p>
+ If the parent did not require explicit bindings but the child does, it is
+ possible that a linked binding in the child may add a JIT binding to the
+ parent. The child will not be allowed to reference the target binding
+ directly, but the parent and other children of the parent may be able to.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="disableCircularProxies"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Prevents Guice from constructing a {@link Proxy} when a circular dependency
+ is found.  By default, circular proxies are not disabled.
+ <p>
+ If a parent injector disables circular proxies, then all child injectors
+ (and private modules within that injector) also disable circular proxies.
+ If a parent does not disable circular proxies, a child injector or private
+ module may optionally declare itself as disabling circular proxies. If it
+ does, the behavior is limited only to that child or any grandchildren. No
+ siblings of the child will disable circular proxies.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Collects configuration information (primarily <i>bindings</i>) which will be
+ used to create an {@link Injector}. Guice provides this object to your
+ application's {@link Module} implementors so they may each contribute
+ their own bindings and other registrations.
+
+ <h3>The Guice Binding EDSL</h3>
+
+ Guice uses an <i>embedded domain-specific language</i>, or EDSL, to help you
+ create bindings simply and readably.  This approach is great for overall
+ usability, but it does come with a small cost: <b>it is difficult to
+ learn how to use the Binding EDSL by reading
+ method-level javadocs</b>.  Instead, you should consult the series of
+ examples below.  To save space, these examples omit the opening
+ {@code binder}, just as you will if your module extends
+ {@link AbstractModule}.
+
+ <pre>
+     bind(ServiceImpl.class);</pre>
+
+ This statement does essentially nothing; it "binds the {@code ServiceImpl}
+ class to itself" and does not change Guice's default behavior.  You may still
+ want to use this if you prefer your {@link Module} class to serve as an
+ explicit <i>manifest</i> for the services it provides.  Also, in rare cases,
+ Guice may be unable to validate a binding at injector creation time unless it
+ is given explicitly.
+
+ <pre>
+     bind(Service.class).to(ServiceImpl.class);</pre>
+
+ Specifies that a request for a {@code Service} instance with no binding
+ annotations should be treated as if it were a request for a
+ {@code ServiceImpl} instance. This <i>overrides</i> the function of any
+ {@link ImplementedBy @ImplementedBy} or {@link ProvidedBy @ProvidedBy}
+ annotations found on {@code Service}, since Guice will have already
+ "moved on" to {@code ServiceImpl} before it reaches the point when it starts
+ looking for these annotations.
+
+ <pre>
+     bind(Service.class).toProvider(ServiceProvider.class);</pre>
+
+ In this example, {@code ServiceProvider} must extend or implement
+ {@code Provider<Service>}. This binding specifies that Guice should resolve
+ an unannotated injection request for {@code Service} by first resolving an
+ instance of {@code ServiceProvider} in the regular way, then calling
+ {@link Provider#get get()} on the resulting Provider instance to obtain the
+ {@code Service} instance.
+
+ <p>The {@link Provider} you use here does not have to be a "factory"; that
+ is, a provider which always <i>creates</i> each instance it provides.
+ However, this is generally a good practice to follow.  You can then use
+ Guice's concept of {@link Scope scopes} to guide when creation should happen
+ -- "letting Guice work for you".
+
+ <pre>
+     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);</pre>
+
+ Like the previous example, but only applies to injection requests that use
+ the binding annotation {@code @Red}.  If your module also includes bindings
+ for particular <i>values</i> of the {@code @Red} annotation (see below),
+ then this binding will serve as a "catch-all" for any values of {@code @Red}
+ that have no exact match in the bindings.
+ 
+ <pre>
+     bind(ServiceImpl.class).in(Singleton.class);
+     // or, alternatively
+     bind(ServiceImpl.class).in(Scopes.SINGLETON);</pre>
+
+ Either of these statements places the {@code ServiceImpl} class into
+ singleton scope.  Guice will create only one instance of {@code ServiceImpl}
+ and will reuse it for all injection requests of this type.  Note that it is
+ still possible to bind another instance of {@code ServiceImpl} if the second
+ binding is qualified by an annotation as in the previous example.  Guice is
+ not overly concerned with <i>preventing</i> you from creating multiple
+ instances of your "singletons", only with <i>enabling</i> your application to
+ share only one instance if that's all you tell Guice you need.
+
+ <p><b>Note:</b> a scope specified in this way <i>overrides</i> any scope that
+ was specified with an annotation on the {@code ServiceImpl} class.
+ 
+ <p>Besides {@link Singleton}/{@link Scopes#SINGLETON}, there are
+ servlet-specific scopes available in
+ {@code com.google.inject.servlet.ServletScopes}, and your Modules can
+ contribute their own custom scopes for use here as well.
+
+ <pre>
+     bind(new TypeLiteral&lt;PaymentService&lt;CreditCard>>() {})
+         .to(CreditCardPaymentService.class);</pre>
+
+ This admittedly odd construct is the way to bind a parameterized type. It
+ tells Guice how to honor an injection request for an element of type
+ {@code PaymentService<CreditCard>}. The class
+ {@code CreditCardPaymentService} must implement the
+ {@code PaymentService<CreditCard>} interface.  Guice cannot currently bind or
+ inject a generic type, such as {@code Set<E>}; all type parameters must be
+ fully specified.
+
+ <pre>
+     bind(Service.class).toInstance(new ServiceImpl());
+     // or, alternatively
+     bind(Service.class).toInstance(SomeLegacyRegistry.getService());</pre>
+
+ In this example, your module itself, <i>not Guice</i>, takes responsibility
+ for obtaining a {@code ServiceImpl} instance, then asks Guice to always use
+ this single instance to fulfill all {@code Service} injection requests.  When
+ the {@link Injector} is created, it will automatically perform field
+ and method injection for this instance, but any injectable constructor on
+ {@code ServiceImpl} is simply ignored.  Note that using this approach results
+ in "eager loading" behavior that you can't control.
+
+ <pre>
+     bindConstant().annotatedWith(ServerHost.class).to(args[0]);</pre>
+
+ Sets up a constant binding. Constant injections must always be annotated.
+ When a constant binding's value is a string, it is eligile for conversion to
+ all primitive types, to {@link Enum#valueOf(Class, String) all enums}, and to
+ {@link Class#forName class literals}. Conversions for other types can be
+ configured using {@link #convertToTypes(Matcher, TypeConverter)
+ convertToTypes()}.
+
+ <pre>
+   {@literal @}Color("red") Color red; // A member variable (field)
+    . . .
+     red = MyModule.class.getDeclaredField("red").getAnnotation(Color.class);
+     bind(Service.class).annotatedWith(red).to(RedService.class);</pre>
+
+ If your binding annotation has parameters you can apply different bindings to
+ different specific values of your annotation.  Getting your hands on the
+ right instance of the annotation is a bit of a pain -- one approach, shown
+ above, is to apply a prototype annotation to a field in your module class, so
+ that you can read this annotation instance and give it to Guice.
+
+ <pre>
+     bind(Service.class)
+         .annotatedWith(Names.named("blue"))
+         .to(BlueService.class);</pre>
+
+ Differentiating by names is a common enough use case that we provided a
+ standard annotation, {@link com.google.inject.name.Named @Named}.  Because of
+ Guice's library support, binding by name is quite easier than in the
+ arbitrary binding annotation case we just saw.  However, remember that these
+ names will live in a single flat namespace with all the other names used in
+ your application.
+
+ <pre>
+     Constructor<T> loneCtor = getLoneCtorFromServiceImplViaReflection();
+     bind(ServiceImpl.class)
+         .toConstructor(loneCtor);</pre>
+
+ In this example, we directly tell Guice which constructor to use in a concrete
+ class implementation. It means that we do not need to place {@literal @}Inject
+ on any of the constructors and that Guice treats the provided constructor as though
+ it were annotated so. It is useful for cases where you cannot modify existing
+ classes and is a bit simpler than using a {@link Provider}.
+
+ <p>The above list of examples is far from exhaustive.  If you can think of
+ how the concepts of one example might coexist with the concepts from another,
+ you can most likely weave the two together.  If the two concepts make no
+ sense with each other, you most likely won't be able to do it.  In a few
+ cases Guice will let something bogus slip by, and will then inform you of
+ the problems at runtime, as soon as you try to create your Injector.
+
+ <p>The other methods of Binder such as {@link #bindScope},
+ {@link #bindInterceptor}, {@link #install}, {@link #requestStaticInjection},
+ {@link #addError} and {@link #currentStage} are not part of the Binding EDSL;
+ you can learn how to use these in the usual way, from the method
+ documentation.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @author kevinb@google.com (Kevin Bourrillion)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Binder -->
+  <!-- start interface com.google.inject.Binding -->
+  <interface name="Binding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for this binding.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the scoped provider guice uses to fulfill requests for this
+ binding.
+
+ @throws UnsupportedOperationException when invoked on a {@link Binding}
+      created via {@link com.google.inject.spi.Elements#getElements}. This
+      method is only supported on {@link Binding}s returned from an injector.]]>
+      </doc>
+    </method>
+    <method name="acceptTargetVisitor" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;? super T, V&gt;"/>
+      <doc>
+      <![CDATA[Accepts a target visitor. Invokes the visitor method specific to this binding's target.
+
+ @param visitor to call back on
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="acceptScopingVisitor" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Accepts a scoping visitor. Invokes the visitor method specific to this binding's scoping.
+
+ @param visitor to call back on
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A mapping from a key (type and optional annotation) to the strategy for getting instances of the
+ type. This interface is part of the introspection API and is intended primarily for use by 
+ tools.
+
+ <p>Bindings are created in several ways:
+ <ul>
+     <li>Explicitly in a module, via {@code bind()} and {@code bindConstant()}
+         statements:
+ <pre>
+     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);
+     bindConstant().annotatedWith(ServerHost.class).to(args[0]);</pre></li>
+     <li>Implicitly by the Injector by following a type's {@link ImplementedBy
+         pointer} {@link ProvidedBy annotations} or by using its {@link Inject annotated} or
+         default constructor.</li>
+     <li>By converting a bound instance to a different type.</li>
+     <li>For {@link Provider providers}, by delegating to the binding for the provided type.</li>
+ </ul>
+
+
+ <p>They exist on both modules and on injectors, and their behaviour is different for each:
+ <ul>
+     <li><strong>Module bindings</strong> are incomplete and cannot be used to provide instances.
+         This is because the applicable scopes and interceptors may not be known until an injector
+         is created. From a tool's perspective, module bindings are like the injector's source
+         code. They can be inspected or rewritten, but this analysis must be done statically.</li>
+     <li><strong>Injector bindings</strong> are complete and valid and can be used to provide
+         instances. From a tools' perspective, injector bindings are like reflection for an
+         injector. They have full runtime information, including the complete graph of injections
+         necessary to satisfy a binding.</li>
+ </ul>
+
+ @param <T> the bound type. The injected is always assignable to this type.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Binding -->
+  <!-- start class com.google.inject.BindingAnnotation -->
+  <class name="BindingAnnotation"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates annotations which are used for binding. Only one such annotation
+ may apply to a single injection point. You must also annotate binder
+ annotations with {@code @Retention(RUNTIME)}. For example:
+
+ <pre>
+   {@code @}Retention(RUNTIME)
+   {@code @}Target({ FIELD, PARAMETER, METHOD })
+   {@code @}BindingAnnotation
+   public {@code @}interface Transactional {}
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.BindingAnnotation -->
+  <!-- start class com.google.inject.ConfigurationException -->
+  <class name="ConfigurationException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ConfigurationException" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a ConfigurationException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <method name="withPartialValue" return="com.google.inject.ConfigurationException"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="partialValue" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a copy of this configuration exception with the specified partial value.]]>
+      </doc>
+    </method>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getPartialValue" return="E"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a value that was only partially computed due to this exception. The caller can use
+ this while collecting additional configuration problems.
+
+ @return the partial value, or {@code null} if none was set. The type of the partial value is
+      specified by the throwing method.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Thrown when a programming error such as a misplaced annotation, illegal binding, or unsupported
+ scope is found. Clients should catch this exception, log it, and stop execution.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ConfigurationException -->
+  <!-- start class com.google.inject.CreationException -->
+  <class name="CreationException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="CreationException" type="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a CreationException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Thrown when errors occur while creating a {@link Injector}. Includes a list of encountered
+ errors. Clients should catch this exception, log it, and stop execution.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.CreationException -->
+  <!-- start class com.google.inject.Exposed -->
+  <class name="Exposed"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Acccompanies a {@literal @}{@link com.google.inject.Provides Provides} method annotation in a
+ private module to indicate that the provided binding is exposed.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Exposed -->
+  <!-- start class com.google.inject.Guice -->
+  <class name="Guice" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules.
+
+ @throws CreationException if one or more errors occur during injector
+     construction]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules.
+
+ @throws CreationException if one or more errors occur during injector
+     creation]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules, in a given development
+ stage.
+
+ @throws CreationException if one or more errors occur during injector
+     creation.]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules, in a given development
+ stage.
+
+ @throws CreationException if one or more errors occur during injector
+     construction]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[The entry point to the Guice framework. Creates {@link Injector}s from
+ {@link Module}s.
+
+ <p>Guice supports a model of development that draws clear boundaries between
+ APIs, Implementations of these APIs, Modules which configure these
+ implementations, and finally Applications which consist of a collection of
+ Modules. It is the Application, which typically defines your {@code main()}
+ method, that bootstraps the Guice Injector using the {@code Guice} class, as
+ in this example:
+ <pre>
+     public class FooApplication {
+       public static void main(String[] args) {
+         Injector injector = Guice.createInjector(
+             new ModuleA(),
+             new ModuleB(),
+             . . .
+             new FooApplicationFlagsModule(args)
+         );
+
+         // Now just bootstrap the application and you're done
+         FooStarter starter = injector.getInstance(FooStarter.class);
+         starter.runApplication();
+       }
+     }
+ </pre>]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Guice -->
+  <!-- start class com.google.inject.ImplementedBy -->
+  <class name="ImplementedBy"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A pointer to the default implementation of a type.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ImplementedBy -->
+  <!-- start class com.google.inject.Inject -->
+  <class name="Inject"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates members of your implementation class (constructors, methods
+ and fields) into which the {@link Injector} should inject values.
+ The Injector fulfills injection requests for:
+
+ <ul>
+ <li>Every instance it constructs. The class being constructed must have
+ exactly one of its constructors marked with {@code @Inject} or must have a
+ constructor taking no parameters. The Injector then proceeds to perform
+ method and field injections.
+ 
+ <li>Pre-constructed instances passed to {@link Injector#injectMembers},
+ {@link com.google.inject.binder.LinkedBindingBuilder#toInstance(Object)} and
+ {@link com.google.inject.binder.LinkedBindingBuilder#toProvider(Provider)}.
+ In this case all constructors are, of course, ignored.
+
+ <li>Static fields and methods of classes which any {@link Module} has
+ specifically requested static injection for, using
+ {@link Binder#requestStaticInjection}.
+ </ul>
+
+ In all cases, a member can be injected regardless of its Java access
+ specifier (private, default, protected, public).
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Inject -->
+  <!-- start interface com.google.inject.Injector -->
+  <interface name="Injector"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="injectMembers"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
+ absence of an injectable constructor.
+
+ <p>Whenever Guice creates an instance, it performs this injection automatically (after first
+ performing constructor injection), so if you're able to let Guice create all your objects for
+ you, you'll never need to use this method.
+
+ @param instance to inject members on
+
+ @see Binder#getMembersInjector(Class) for a preferred alternative that supports checks before
+  run time]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}.
+
+ @param typeLiteral type to get members injector for
+ @see Binder#getMembersInjector(TypeLiteral) for an alternative that offers up front error
+  detection
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. When feasible, use {@link Binder#getMembersInjector(TypeLiteral)}
+ instead to get increased up front error detection.
+
+ @param type type to get members injector for
+ @see Binder#getMembersInjector(Class) for an alternative that offers up front error
+  detection
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getBindings" return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns this injector's <strong>explicit</strong> bindings.
+
+ <p>The returned map does not include bindings inherited from a {@link #getParent() parent
+ injector}, should one exist. The returned map is guaranteed to iterate (for example, with
+ its {@link Map#entrySet()} iterator) in the order of insertion. In other words, the order in
+ which bindings appear in user Modules.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.]]>
+      </doc>
+    </method>
+    <method name="getAllBindings" return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a snapshot of this injector's bindings, <strong>both explicit and
+ just-in-time</strong>. The returned map is immutable; it contains only the bindings that were
+ present when {@code getAllBindings()} was invoked. Subsequent calls may return a map with
+ additional just-in-time bindings.
+
+ <p>The returned map does not include bindings inherited from a {@link #getParent() parent
+ injector}, should one exist.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="getBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the binding for the given injection key. This will be an explicit bindings if the key
+ was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
+ be created if necessary.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+
+ @throws ConfigurationException if this injector cannot find or create the binding.]]>
+      </doc>
+    </method>
+    <method name="getBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the binding for the given type. This will be an explicit bindings if the injection key
+ was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
+ be created if necessary.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+
+ @throws ConfigurationException if this injector cannot find or create the binding.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getExistingBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the binding if it already exists, or null if does not exist. Unlike
+ {@link #getBinding(Key)}, this does not attempt to create just-in-time bindings
+ for keys that aren't bound.
+ 
+ <p> This method is part of the Guice SPI and is intended for use by tools and extensions.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="findBindingsByType" return="java.util.List&lt;com.google.inject.Binding&lt;T&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns all explicit bindings for {@code type}.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key. When feasible, avoid
+ using this method, in favor of having Guice inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @see Binder#getProvider(Key) for an alternative that offers up front error detection]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given type. When feasible, avoid
+ using this method, in favor of having Guice inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @see Binder#getProvider(Class) for an alternative that offers up front error detection]]>
+      </doc>
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the appropriate instance for the given injection key; equivalent to {@code
+ getProvider(key).get()}. When feasible, avoid using this method, in favor of having Guice
+ inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @throws ProvisionException if there was a runtime failure while providing an instance.]]>
+      </doc>
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the appropriate instance for the given injection type; equivalent to {@code
+ getProvider(type).get()}. When feasible, avoid using this method, in favor of having Guice
+ inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @throws ProvisionException if there was a runtime failure while providing an instance.]]>
+      </doc>
+    </method>
+    <method name="getParent" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns this injector's parent, or {@code null} if this is a top-level injector.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="createChildInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injector that inherits all state from this injector. All bindings, scopes,
+ interceptors and type converters are inherited -- they are visible to the child injector.
+ Elements of the child injector are not visible to its parent.
+
+ <p>Just-in-time bindings created for child injectors will be created in an ancestor injector
+ whenever possible. This allows for scoped instances to be shared between injectors. Use
+ explicit bindings to prevent bindings from being shared with the parent injector.  Optional
+ injections in just-in-time bindings (created in the parent injector) may be silently
+ ignored if the optional dependencies are from the child injector.
+
+ <p>No key may be bound by both an injector and one of its ancestors. This includes just-in-time
+ bindings. The lone exception is the key for {@code Injector.class}, which is bound by each
+ injector to itself.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="createChildInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a new injector that inherits all state from this injector. All bindings, scopes,
+ interceptors and type converters are inherited -- they are visible to the child injector.
+ Elements of the child injector are not visible to its parent.
+
+ <p>Just-in-time bindings created for child injectors will be created in an ancestor injector
+ whenever possible. This allows for scoped instances to be shared between injectors. Use
+ explicit bindings to prevent bindings from being shared with the parent injector.
+
+ <p>No key may be bound by both an injector and one of its ancestors. This includes just-in-time
+ bindings. The lone exception is the key for {@code Injector.class}, which is bound by each
+ injector to itself.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getScopeBindings" return="java.util.Map&lt;java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;, com.google.inject.Scope&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a map containing all scopes in the injector. The maps keys are scoping annotations
+ like {@code Singleton.class}, and the values are scope instances, such as {@code
+ Scopes.SINGLETON}. The returned map is immutable.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="getTypeConverterBindings" return="java.util.Set&lt;com.google.inject.spi.TypeConverterBinding&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a set containing all type converter bindings in the injector. The returned set is
+ immutable.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Builds the graphs of objects that make up your application. The injector tracks the dependencies
+ for each type and uses bindings to inject them. This is the core of Guice, although you rarely
+ interact with it directly. This "behind-the-scenes" operation is what distinguishes dependency
+ injection from its cousin, the service locator pattern.
+
+ <p>Contains several default bindings:
+
+ <ul>
+ <li>This {@link Injector} instance itself
+ <li>A {@code Provider<T>} for each binding of type {@code T}
+ <li>The {@link java.util.logging.Logger} for the class being injected
+ <li>The {@link Stage} in which the Injector was created
+ </ul>
+
+ Injectors are created using the facade class {@link Guice}.
+
+ <p>An injector can also {@link #injectMembers(Object) inject the dependencies} of
+ already-constructed instances. This can be used to interoperate with objects created by other
+ frameworks or services.
+
+ <p>Injectors can be {@link #createChildInjector(Iterable) hierarchical}. Child injectors inherit
+ the configuration of their parent injectors, but the converse does not hold.
+
+ <p>The injector's {@link #getBindings() internal bindings} are available for introspection. This
+ enables tools and extensions to operate on an injector reflectively.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Injector -->
+  <!-- start class com.google.inject.Key -->
+  <class name="Key" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Key" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo} annotated with
+ {@code @Bar}:
+
+ <p>{@code new Key<Foo>(Bar.class) {}}.]]>
+      </doc>
+    </constructor>
+    <constructor name="Key" type="java.lang.annotation.Annotation"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo} annotated with
+ {@code @Bar}:
+
+ <p>{@code new Key<Foo>(new Bar()) {}}.]]>
+      </doc>
+    </constructor>
+    <constructor name="Key"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo}:
+
+ <p>{@code new Key<Foo>() {}}.]]>
+      </doc>
+    </constructor>
+    <method name="getTypeLiteral" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the key type.]]>
+      </doc>
+    </method>
+    <method name="getAnnotationType" return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the annotation type.]]>
+      </doc>
+    </method>
+    <method name="getAnnotation" return="java.lang.annotation.Annotation"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the annotation.]]>
+      </doc>
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="ofType" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new key of the specified type with the same annotation as this
+ key.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="ofType" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a new key of the specified type with the same annotation as this
+ key.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="ofType" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new key of the specified type with the same annotation as this
+ key.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="hasAttributes" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if this key has annotation attributes.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="withoutAttributes" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns this key without annotation attributes, i.e. with only the
+ annotation type.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Binding key consisting of an injection type and an optional annotation.
+ Matches the type and annotation at a point of injection.
+
+ <p>For example, {@code Key.get(Service.class, Transactional.class)} will
+ match:
+
+ <pre>
+   {@literal @}Inject
+   public void setService({@literal @}Transactional Service service) {
+     ...
+   }
+ </pre>
+
+ <p>{@code Key} supports generic types via subclassing just like {@link
+ TypeLiteral}.
+
+ <p>Keys do not differentiate between primitive types (int, char, etc.) and
+ their correpsonding wrapper types (Integer, Character, etc.). Primitive
+ types will be replaced with their wrapper types when keys are created.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Key -->
+  <!-- start interface com.google.inject.MembersInjector -->
+  <interface name="MembersInjector"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="injectMembers"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
+ absence of an injectable constructor.
+
+ <p>Whenever Guice creates an instance, it performs this injection automatically (after first
+ performing constructor injection), so if you're able to let Guice create all your objects for
+ you, you'll never need to use this method.
+
+ @param instance to inject members on. May be {@code null}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Injects dependencies into the fields and methods on instances of type {@code T}. Ignores the
+ presence or absence of an injectable constructor.
+
+ @param <T> type to inject members of
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.MembersInjector -->
+  <!-- start interface com.google.inject.Module -->
+  <interface name="Module"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Contributes bindings and other configurations for this module to {@code binder}.
+
+ <p><strong>Do not invoke this method directly</strong> to install submodules. Instead use
+ {@link Binder#install(Module)}, which ensures that {@link Provides provider methods} are
+ discovered.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A module contributes configuration information, typically interface
+ bindings, which will be used to create an {@link Injector}. A Guice-based
+ application is ultimately composed of little more than a set of
+ {@code Module}s and some bootstrapping code.
+
+ <p>Your Module classes can use a more streamlined syntax by extending
+ {@link AbstractModule} rather than implementing this interface directly.
+
+ <p>In addition to the bindings configured via {@link #configure}, bindings
+ will be created for all methods annotated with {@literal @}{@link Provides}.
+ Use scope and binding annotations on these methods to configure the
+ bindings.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Module -->
+  <!-- start class com.google.inject.OutOfScopeException -->
+  <class name="OutOfScopeException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="OutOfScopeException" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="OutOfScopeException" type="java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="OutOfScopeException" type="java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <doc>
+    <![CDATA[Thrown from {@link Provider#get} when an attempt is made to access a scoped
+ object while the scope in question is not currently active.
+
+ @author kevinb@google.com (Kevin Bourrillion)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.OutOfScopeException -->
+  <!-- start interface com.google.inject.PrivateBinder -->
+  <interface name="PrivateBinder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binder"/>
+    <method name="expose"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes the binding for {@code key} available to the enclosing environment]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to the enclosing environment. Use {@link
+ com.google.inject.binder.AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to the enclosing environment. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="withSource" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <method name="skipSources" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classesToSkip" type="java.lang.Class[]"/>
+    </method>
+    <doc>
+    <![CDATA[Returns a binder whose configuration information is hidden from its environment by default. See
+ {@link com.google.inject.PrivateModule PrivateModule} for details.
+ 
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.PrivateBinder -->
+  <!-- start class com.google.inject.PrivateModule -->
+  <class name="PrivateModule" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Module"/>
+    <constructor name="PrivateModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="true"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="configure"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates bindings and other configurations private to this module. Use {@link #expose(Class)
+ expose()} to make the bindings in this module available externally.]]>
+      </doc>
+    </method>
+    <method name="expose"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Makes the binding for {@code key} available to other modules and the injector.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to other modules and the injector. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to other modules and the injector. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="binder" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the current binder.]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[@see Binder#bindScope(Class, Scope)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Key)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Class)]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#bindConstant()]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[@see Binder#install(Module)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[@see Binder#addError(String, Object[])]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Throwable)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Message)]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[@see Binder#requestInjection(Object)]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[@see Binder#requestStaticInjection(Class[])]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindInterceptor(com.google.inject.matcher.Matcher, com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Instructs Guice to require a binding to the given key.]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Instructs Guice to require a binding to the given type.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Key)]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Class)]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[@see Binder#convertToTypes(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeConverter)]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#currentStage()]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(Class)]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[@see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener)]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A module whose configuration information is hidden from its environment by default. Only bindings
+ that are explicitly exposed will be available to other modules and to the users of the injector.
+ This module may expose the bindings it creates and the bindings of the modules it installs.
+
+ <p>A private module can be nested within a regular module or within another private module using
+ {@link Binder#install install()}.  Its bindings live in a new environment that inherits bindings,
+ type converters, scopes, and interceptors from the surrounding ("parent") environment.  When you
+ nest multiple private modules, the result is a tree of environments where the injector's
+ environment is the root.
+
+ <p>Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link
+ com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link
+ Exposed} annotation:
+
+ <pre>
+ public class FooBarBazModule extends PrivateModule {
+   protected void configure() {
+     bind(Foo.class).to(RealFoo.class);
+     expose(Foo.class);
+
+     install(new TransactionalBarModule());
+     expose(Bar.class).annotatedWith(Transactional.class);
+
+     bind(SomeImplementationDetail.class);
+     install(new MoreImplementationDetailsModule());
+   }
+
+   {@literal @}Provides {@literal @}Exposed
+   public Baz provideBaz() {
+     return new SuperBaz();
+   }
+ }
+ </pre>
+
+ <p>Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent
+ injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the
+ root environment. Such bindings are shared among all environments in the tree.
+ 
+ <p>The scope of a binding is constrained to its environment. A singleton bound in a private
+ module will be unique to its environment. But a binding for the same type in a different private
+ module will yield a different instance.
+
+ <p>A shared binding that injects the {@code Injector} gets the root injector, which only has
+ access to bindings in the root environment. An explicit binding that injects the {@code Injector}
+ gets access to all bindings in the child environment.
+
+ <p>To promote a just-in-time binding to an explicit binding, bind it:
+ <pre>
+   bind(FooImpl.class);
+ </pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.PrivateModule -->
+  <!-- start class com.google.inject.ProvidedBy -->
+  <class name="ProvidedBy"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A pointer to the default provider type for a type.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ProvidedBy -->
+  <!-- start interface com.google.inject.Provider -->
+  <interface name="Provider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="javax.inject.Provider&lt;T&gt;"/>
+    <method name="get" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Provides an instance of {@code T}. Must never return {@code null}.
+
+ @throws OutOfScopeException when an attempt is made to access a scoped object while the scope
+     in question is not currently active
+ @throws ProvisionException if an instance cannot be provided. Such exceptions include messages
+     and throwables to describe why provision failed.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An object capable of providing instances of type {@code T}. Providers are used in numerous ways
+ by Guice:
+
+ <ul>
+ <li>When the default means for obtaining instances (an injectable or parameterless constructor)
+ is insufficient for a particular binding, the module can specify a custom {@code Provider}
+ instead, to control exactly how Guice creates or obtains instances for the binding.
+
+ <li>An implementation class may always choose to have a {@code Provider<T>} instance injected,
+ rather than having a {@code T} injected directly.  This may give you access to multiple
+ instances, instances you wish to safely mutate and discard, instances which are out of scope
+ (e.g. using a {@code @RequestScoped} object from within a {@code @SessionScoped} object), or
+ instances that will be initialized lazily.
+
+ <li>A custom {@link Scope} is implemented as a decorator of {@code Provider<T>}, which decides
+ when to delegate to the backing provider and when to provide the instance some other way.
+
+ <li>The {@link Injector} offers access to the {@code Provider<T>} it uses to fulfill requests
+ for a given key, via the {@link Injector#getProvider} methods.
+ </ul>
+
+ @param <T> the type of object this provides
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Provider -->
+  <!-- start class com.google.inject.Provides -->
+  <class name="Provides"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates methods of a {@link Module} to create a provider method binding. The method's return
+ type is bound to it's returned value. Guice will pass dependencies to the method as parameters.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Provides -->
+  <!-- start class com.google.inject.ProvisionException -->
+  <class name="ProvisionException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ProvisionException" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a ProvisionException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <constructor name="ProvisionException" type="java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="ProvisionException" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Indicates that there was a runtime failure while providing an instance.
+
+ @author kevinb@google.com (Kevin Bourrillion)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ProvisionException -->
+  <!-- start interface com.google.inject.Scope -->
+  <interface name="Scope"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="scope" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <param name="unscoped" type="com.google.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Scopes a provider. The returned provider returns objects from this scope.
+ If an object does not exist in this scope, the provider can use the given
+ unscoped provider to retrieve one.
+
+ <p>Scope implementations are strongly encouraged to override
+ {@link Object#toString} in the returned provider and include the backing
+ provider's {@code toString()} output.
+
+ @param key binding key
+ @param unscoped locates an instance when one doesn't already exist in this
+  scope.
+ @return a new provider which only delegates to the given unscoped provider
+  when an instance of the requested object doesn't already exist in this
+  scope]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[A short but useful description of this scope.  For comparison, the standard
+ scopes that ship with guice use the descriptions
+ {@code "Scopes.SINGLETON"}, {@code "ServletScopes.SESSION"} and
+ {@code "ServletScopes.REQUEST"}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A scope is a level of visibility that instances provided by Guice may have.
+ By default, an instance created by the {@link Injector} has <i>no scope</i>,
+ meaning it has no state from the framework's perspective -- the
+ {@code Injector} creates it, injects it once into the class that required it,
+ and then immediately forgets it. Associating a scope with a particular
+ binding allows the created instance to be "remembered" and possibly used
+ again for other injections.
+
+ <p>An example of a scope is {@link Scopes#SINGLETON}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Scope -->
+  <!-- start class com.google.inject.ScopeAnnotation -->
+  <class name="ScopeAnnotation"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates annotations which are used for scoping. Only one such annotation
+ may apply to a single implementation class. You must also annotate scope
+ annotations with {@code @Retention(RUNTIME)}. For example:
+
+ <pre>
+   {@code @}Retention(RUNTIME)
+   {@code @}Target(TYPE, METHOD)
+   {@code @}ScopeAnnotation
+   public {@code @}interface SessionScoped {}
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ScopeAnnotation -->
+  <!-- start class com.google.inject.Scopes -->
+  <class name="Scopes" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="isSingleton" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns true if {@code binding} is singleton-scoped. If the binding is a {@link
+ com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it
+ was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will
+ also true if the target binding is singleton-scoped.
+
+ @since 3.0]]>
+      </doc>
+    </method>
+    <field name="SINGLETON" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[One instance per {@link Injector}. Also see {@code @}{@link Singleton}.]]>
+      </doc>
+    </field>
+    <field name="NO_SCOPE" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[No scope; the same as not applying any scope at all.  Each time the
+ Injector obtains an instance of an object with "no scope", it injects this
+ instance then immediately forgets it.  When the next request for the same
+ binding arrives it will need to obtain the instance over again.
+
+ <p>This exists only in case a class has been annotated with a scope
+ annotation such as {@link Singleton @Singleton}, and you need to override
+ this to "no scope" in your binding.
+
+ @since 2.0]]>
+      </doc>
+    </field>
+    <doc>
+    <![CDATA[Built-in scope implementations.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Scopes -->
+  <!-- start class com.google.inject.Singleton -->
+  <class name="Singleton"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want only one instance
+ (per {@link Injector}) to be reused for all injections for that binding.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Singleton -->
+  <!-- start class com.google.inject.Stage -->
+  <class name="Stage" extends="java.lang.Enum&lt;com.google.inject.Stage&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.Stage[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[The stage we're running in.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Stage -->
+  <!-- start class com.google.inject.TypeLiteral -->
+  <class name="TypeLiteral" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="TypeLiteral"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new type literal. Derives represented class from type
+ parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.]]>
+      </doc>
+    </constructor>
+    <method name="getRawType" return="java.lang.Class&lt;? super T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the raw (non-generic) type for this type.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getType" return="java.lang.reflect.Type"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets underlying {@code Type} instance.]]>
+      </doc>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Gets type literal for the given {@code Type} instance.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets type literal for the given {@code Class} instance.]]>
+      </doc>
+    </method>
+    <method name="getSupertype" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="supertype" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns the generic form of {@code supertype}. For example, if this is {@code
+ ArrayList<String>}, this returns {@code Iterable<String>} given the input {@code
+ Iterable.class}.
+
+ @param supertype a superclass of, or interface implemented by, this.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getFieldType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="field" type="java.lang.reflect.Field"/>
+      <doc>
+      <![CDATA[Returns the resolved generic type of {@code field}.
+
+ @param field a field defined by this or any superclass.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getParameterTypes" return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodOrConstructor" type="java.lang.reflect.Member"/>
+      <doc>
+      <![CDATA[Returns the resolved generic parameter types of {@code methodOrConstructor}.
+
+ @param methodOrConstructor a method or constructor defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getExceptionTypes" return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodOrConstructor" type="java.lang.reflect.Member"/>
+      <doc>
+      <![CDATA[Returns the resolved generic exception types thrown by {@code constructor}.
+
+ @param methodOrConstructor a method or constructor defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getReturnType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="method" type="java.lang.reflect.Method"/>
+      <doc>
+      <![CDATA[Returns the resolved generic return type of {@code method}.
+
+ @param method a method defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Represents a generic type {@code T}. Java doesn't yet provide a way to
+ represent generic types, so this class does. Forces clients to create a
+ subclass of this class which enables retrieval the type information even at
+ runtime.
+
+ <p>For example, to create a type literal for {@code List<String>}, you can
+ create an empty anonymous inner class:
+
+ <p>
+ {@code TypeLiteral<List<String>> list = new TypeLiteral<List<String>>() {};}
+
+ <p>Along with modeling generic types, this class can resolve type parameters.
+ For example, to figure out what type {@code keySet()} returns on a {@code
+ Map<Integer, String>}, use this code:<pre>   {@code
+
+   TypeLiteral<Map<Integer, String>> mapType
+       = new TypeLiteral<Map<Integer, String>>() {};
+   TypeLiteral<?> keySetType
+       = mapType.getReturnType(Map.class.getMethod("keySet"));
+   System.out.println(keySetType); // prints "Set<Integer>"}</pre>
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.TypeLiteral -->
+</package>
+<package name="com.google.inject.assistedinject">
+  <!-- start class com.google.inject.assistedinject.Assisted -->
+  <class name="Assisted"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates an injected parameter or field whose value comes from an argument to a factory method.
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.Assisted -->
+  <!-- start class com.google.inject.assistedinject.AssistedInject -->
+  <class name="AssistedInject"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[<p>
+ When used in tandem with {@link FactoryModuleBuilder}, constructors annotated with 
+ {@code @AssistedInject} indicate that multiple constructors can be injected, each with different
+ parameters. AssistedInject annotations should not be mixed with {@literal @}{@link Inject}
+ annotations. The assisted parameters must exactly match one corresponding factory method within
+ the factory interface, but the parameters do not need to be in the same order. Constructors
+ annotated with AssistedInject <b>are</b> created by Guice and receive all the benefits
+ (such as AOP).
+ 
+ <p>
+ <strong>Obsolete Usage:</strong> When used in tandem with {@link FactoryProvider}, constructors
+ annotated with {@code @AssistedInject} trigger a "backwards compatibility mode". The assisted
+ parameters must exactly match one corresponding factory method within the factory interface and
+ all must be in the same order as listed in the factory. In this backwards compatable mode,
+ constructors annotated with AssistedInject <b>are not</b> created by Guice and thus receive
+ none of the benefits.
+ 
+ <p>
+ Constructor parameters must be either supplied by the factory interface and marked with
+ <code>@Assisted</code>, or they must be injectable.
+ 
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.AssistedInject -->
+  <!-- start interface com.google.inject.assistedinject.AssistedInjectBinding -->
+  <interface name="AssistedInjectBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the {@link Key} for the factory binding.]]>
+      </doc>
+    </method>
+    <method name="getAssistedMethods" return="java.util.Collection&lt;com.google.inject.assistedinject.AssistedMethod&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns an {@link AssistedMethod} for each method in the factory.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding for a factory created by FactoryModuleBuilder.
+ 
+ @param <T> The fully qualified type of the factory.
+  
+ @since 3.0
+ @author ramakrishna@google.com (Ramakrishna Rajanna)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.assistedinject.AssistedInjectBinding -->
+  <!-- start interface com.google.inject.assistedinject.AssistedInjectTargetVisitor -->
+  <interface name="AssistedInjectTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="assistedInjectBinding" type="com.google.inject.assistedinject.AssistedInjectBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visits an {@link AssistedInjectBinding} created through {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A visitor for the AssistedInject extension.
+ <p>
+ If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ {@link FactoryModuleBuilder} will be visited through this interface.
+
+ @since 3.0
+ @author ramakrishna@google.com (Ramakrishna Rajanna)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.assistedinject.AssistedInjectTargetVisitor -->
+  <!-- start interface com.google.inject.assistedinject.AssistedMethod -->
+  <interface name="AssistedMethod"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getFactoryMethod" return="java.lang.reflect.Method"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the factory method that is being assisted.]]>
+      </doc>
+    </method>
+    <method name="getImplementationType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the implementation type that will be created when the method is
+ used.]]>
+      </doc>
+    </method>
+    <method name="getImplementationConstructor" return="java.lang.reflect.Constructor&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the constructor that will be used to construct instances of the 
+ implementation.]]>
+      </doc>
+    </method>
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all non-assisted dependencies required to construct and inject
+ the implementation.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Details about how a method in an assisted inject factory will be assisted.
+ 
+ @since 3.0
+ @author ramakrishna@google.com (Ramakrishna Rajanna)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.assistedinject.AssistedMethod -->
+  <!-- start class com.google.inject.assistedinject.FactoryModuleBuilder -->
+  <class name="FactoryModuleBuilder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="FactoryModuleBuilder"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.Key&lt;T&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.Key&lt;T&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="build" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryInterface" type="java.lang.Class&lt;F&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="build" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryInterface" type="com.google.inject.TypeLiteral&lt;F&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="build" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryInterface" type="com.google.inject.Key&lt;F&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[Provides a factory that combines the caller's arguments with injector-supplied values to
+ construct objects.
+
+ <h3>Defining a factory</h3>
+ Create an interface whose methods return the constructed type, or any of its supertypes. The
+ method's parameters are the arguments required to build the constructed type.
+
+ <pre>public interface PaymentFactory {
+   Payment create(Date startDate, Money amount);
+ }</pre>
+
+ You can name your factory methods whatever you like, such as <i>create</i>, <i>createPayment</i>
+ or <i>newPayment</i>.
+
+ <h3>Creating a type that accepts factory parameters</h3>
+ {@code constructedType} is a concrete class with an {@literal @}{@link com.google.inject.Inject
+ Inject}-annotated constructor. In addition to injector-supplied parameters, the constructor
+ should have parameters that match each of the factory method's parameters. Each factory-supplied
+ parameter requires an {@literal @}{@link Assisted} annotation. This serves to document that the
+ parameter is not bound by your application's modules.
+
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted Date startDate</strong>,
+      <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }
+ }</pre>
+ 
+ <h3>Multiple factory methods for the same type</h3>
+ If the factory contains many methods that return the same type, you can create multiple
+ constructors in your concrete class, each constructor marked with with
+ {@literal @}{@link AssistedInject}, in order to match the different parameters types of the
+ factory methods. 
+ 
+ <pre>public interface PaymentFactory {
+    Payment create(Date startDate, Money amount);
+    Payment createWithoutDate(Money amount);
+ }
+ 
+ public class RealPayment implements Payment {
+  {@literal @}AssistedInject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+     <strong>{@literal @}Assisted Date startDate</strong>,
+     <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }
+   
+  {@literal @}AssistedInject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+     <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }   
+ }</pre> 
+
+ <h3>Configuring simple factories</h3>
+ In your {@link Module module}, install a {@code FactoryModuleBuilder} that creates the
+ factory:
+
+ <pre>install(new FactoryModuleBuilder()
+     .implement(Payment.class, RealPayment.class)
+     .build(PaymentFactory.class);</pre>
+
+ As a side-effect of this binding, Guice will inject the factory to initialize it for use. The
+ factory cannot be used until the injector has been initialized.
+ 
+ <h3>Configuring complex factories</h3>
+ Factories can create an arbitrary number of objects, one per each method.  Each factory
+ method can be configured using <code>.implement</code>.
+
+ <pre>public interface OrderFactory {
+    Payment create(Date startDate, Money amount);
+    Shipment create(Customer customer, Item item);
+    Receipt create(Payment payment, Shipment shipment);
+ }
+ 
+ [...]
+ 
+ install(new FactoryModuleBuilder()
+     .implement(Payment.class, RealPayment.class)
+     // excluding .implement for Shipment means the implementation class
+     // will be 'Shipment' itself, which is legal if it's not an interface.
+     .implement(Receipt.class, RealReceipt.class)
+     .build(OrderFactory.class);</pre>
+ </pre>
+
+ <h3>Using the factory</h3>
+ Inject your factory into your application classes. When you use the factory, your arguments
+ will be combined with values from the injector to construct an instance.
+
+ <pre>public class PaymentAction {
+   {@literal @}Inject private PaymentFactory paymentFactory;
+
+   public void doPayment(Money amount) {
+     Payment payment = paymentFactory.create(new Date(), amount);
+     payment.apply();
+   }
+ }</pre>
+
+ <h3>Making parameter types distinct</h3>
+ The types of the factory method's parameters must be distinct. To use multiple parameters of
+ the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the
+ parameters. The names must be applied to the factory method's parameters:
+
+ <pre>public interface PaymentFactory {
+   Payment create(
+       <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+       <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+       Money amount);
+ } </pre>
+
+ ...and to the concrete type's constructor parameters:
+
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+      <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+      <strong>{@literal @}Assisted</strong> Money amount) {
+     ...
+   }
+ }</pre>
+
+ <h3>Values are created by Guice</h3>
+ Returned factories use child injectors to create values. The values are eligible for method
+ interception. In addition, {@literal @}{@literal Inject} members will be injected before they are
+ returned.
+
+ <h3>More configuration options</h3>
+ In addition to simply specifying an implementation class for any returned type, factories' return
+ values can be automatic or can be configured to use annotations:
+ <p/>
+ If you just want to return the types specified in the factory, do not configure any
+ implementations:
+
+ <pre>public interface FruitFactory {
+   Apple getApple(Color color);
+ }
+ ...
+ protected void configure() {
+   install(new FactoryModuleBuilder().build(FruitFactory.class));
+ }</pre>
+
+ Note that any type returned by the factory in this manner needs to be an implementation class.
+ <p/>
+ To return two different implementations for the same interface from your factory, use binding
+ annotations on your return types:
+
+ <pre>interface CarFactory {
+   {@literal @}Named("fast") Car getFastCar(Color color);
+   {@literal @}Named("clean") Car getCleanCar(Color color);
+ }
+ ...
+ protected void configure() {
+   install(new FactoryModuleBuilder()
+       .implement(Car.class, Names.named("fast"), Porsche.class)
+       .implement(Car.class, Names.named("clean"), Prius.class)
+       .build(CarFactory.class));
+ }</pre>
+ 
+ <h3>Implementation limitations</h3>
+ As a limitation of the implementation, it is prohibited to declare a factory method that
+ accepts a {@code Provider} as one of its arguments.
+
+ @since 3.0
+ @author schmitt@google.com (Peter Schmitt)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.FactoryModuleBuilder -->
+  <!-- start class com.google.inject.assistedinject.FactoryProvider -->
+  <class name="FactoryProvider" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="use {@link FactoryModuleBuilder} instead.">
+    <implements name="com.google.inject.Provider&lt;F&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="newFactory" return="com.google.inject.Provider&lt;F&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryType" type="java.lang.Class&lt;F&gt;"/>
+      <param name="implementationType" type="java.lang.Class&lt;?&gt;"/>
+    </method>
+    <method name="newFactory" return="com.google.inject.Provider&lt;F&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryType" type="com.google.inject.TypeLiteral&lt;F&gt;"/>
+      <param name="implementationType" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+    </method>
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="F"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[<strong>Obsolete.</strong> Prefer {@link FactoryModuleBuilder} for its more concise API and
+ additional capability.
+
+ <p>Provides a factory that combines the caller's arguments with injector-supplied values to
+ construct objects.
+
+ <h3>Defining a factory</h3>
+ Create an interface whose methods return the constructed type, or any of its supertypes. The
+ method's parameters are the arguments required to build the constructed type.
+ <pre>public interface PaymentFactory {
+   Payment create(Date startDate, Money amount);
+ }</pre>
+ You can name your factory methods whatever you like, such as <i>create</i>, <i>createPayment</i>
+ or <i>newPayment</i>.
+
+ <h3>Creating a type that accepts factory parameters</h3>
+ {@code constructedType} is a concrete class with an {@literal @}{@link Inject}-annotated
+ constructor. In addition to injector-supplied parameters, the constructor should have
+ parameters that match each of the factory method's parameters. Each factory-supplied parameter
+ requires an {@literal @}{@link Assisted} annotation. This serves to document that the parameter
+ is not bound by your application's modules.
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted Date startDate</strong>,
+      <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }
+ }</pre>
+ Any parameter that permits a null value should also be annotated {@code @Nullable}.
+
+ <h3>Configuring factories</h3>
+ In your {@link com.google.inject.Module module}, bind the factory interface to the returned
+ factory:
+ <pre>bind(PaymentFactory.class).toProvider(
+     FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));</pre>
+ As a side-effect of this binding, Guice will inject the factory to initialize it for use. The
+ factory cannot be used until the injector has been initialized.
+
+ <h3>Using the factory</h3>
+ Inject your factory into your application classes. When you use the factory, your arguments
+ will be combined with values from the injector to construct an instance.
+ <pre>public class PaymentAction {
+   {@literal @}Inject private PaymentFactory paymentFactory;
+
+   public void doPayment(Money amount) {
+     Payment payment = paymentFactory.create(new Date(), amount);
+     payment.apply();
+   }
+ }</pre>
+
+ <h3>Making parameter types distinct</h3>
+ The types of the factory method's parameters must be distinct. To use multiple parameters of
+ the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the
+ parameters. The names must be applied to the factory method's parameters:
+
+ <pre>public interface PaymentFactory {
+   Payment create(
+       <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+       <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+       Money amount);
+ } </pre>
+ ...and to the concrete type's constructor parameters:
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+      <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+      <strong>{@literal @}Assisted</strong> Money amount) {
+     ...
+   }
+ }</pre>
+
+ <h3>Values are created by Guice</h3>
+ Returned factories use child injectors to create values. The values are eligible for method
+ interception. In addition, {@literal @}{@literal Inject} members will be injected before they are
+ returned.
+
+ <h3>Backwards compatibility using {@literal @}AssistedInject</h3>
+ Instead of the {@literal @}Inject annotation, you may annotate the constructed classes with
+ {@literal @}{@link AssistedInject}. This triggers a limited backwards-compatability mode.
+
+ <p>Instead of matching factory method arguments to constructor parameters using their names, the
+ <strong>parameters are matched by their order</strong>. The first factory method argument is
+ used for the first {@literal @}Assisted constructor parameter, etc.. Annotation names have no
+ effect.
+
+ <p>Returned values are <strong>not created by Guice</strong>. These types are not eligible for
+ method interception. They do receive post-construction member injection.
+
+ @param <F> The factory interface
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)
+ @author dtm@google.com (Daniel Martin)
+ 
+ @deprecated use {@link FactoryModuleBuilder} instead.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.FactoryProvider -->
+</package>
+<package name="com.google.inject.binder">
+  <!-- start interface com.google.inject.binder.AnnotatedBindingBuilder -->
+  <interface name="AnnotatedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"/>
+    <method name="annotatedWith" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedBindingBuilder -->
+  <!-- start interface com.google.inject.binder.AnnotatedConstantBindingBuilder -->
+  <interface name="AnnotatedConstantBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="annotatedWith" return="com.google.inject.binder.ConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.binder.ConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedConstantBindingBuilder -->
+  <!-- start interface com.google.inject.binder.AnnotatedElementBuilder -->
+  <interface name="AnnotatedElementBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="annotatedWith"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedElementBuilder -->
+  <!-- start interface com.google.inject.binder.ConstantBindingBuilder -->
+  <interface name="ConstantBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="int"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="long"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="boolean"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="double"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="float"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="short"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="char"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="byte"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="E extends java.lang.Enum&lt;E&gt;"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Binds to a constant value.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.ConstantBindingBuilder -->
+  <!-- start interface com.google.inject.binder.LinkedBindingBuilder -->
+  <interface name="LinkedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.binder.ScopedBindingBuilder"/>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="implementation" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="implementation" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetKey" type="com.google.inject.Key&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toInstance"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @see com.google.inject.Injector#injectMembers]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="provider" type="com.google.inject.Provider&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @see com.google.inject.Injector#injectMembers]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerType" type="java.lang.Class&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerType" type="com.google.inject.TypeLiteral&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerKey" type="com.google.inject.Key&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toConstructor" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructor" type="java.lang.reflect.Constructor&lt;S&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="toConstructor" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructor" type="java.lang.reflect.Constructor&lt;S&gt;"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;? extends S&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.LinkedBindingBuilder -->
+  <!-- start interface com.google.inject.binder.ScopedBindingBuilder -->
+  <interface name="ScopedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="in"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="in"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="asEagerSingleton"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Instructs the {@link com.google.inject.Injector} to eagerly initialize this
+ singleton-scoped binding upon creation. Useful for application
+ initialization logic.  See the EDSL examples at
+ {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.ScopedBindingBuilder -->
+</package>
+<package name="com.google.inject.grapher">
+  <!-- start interface com.google.inject.grapher.BindingEdge -->
+  <interface name="BindingEdge"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="setType"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.grapher.BindingEdge.Type"/>
+    </method>
+    <doc>
+    <![CDATA[Interface for an edge that connects an interface to the type or instance
+ that is bound to implement it.
+
+ @author phopkins@gmail.com (Pete Hopkins)
+
+ @param <K> The type for node IDs.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.BindingEdge -->
+  <!-- start interface com.google.inject.grapher.BindingEdge.Factory -->
+  <interface name="BindingEdge.Factory"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newBindingEdge" return="T extends com.google.inject.grapher.BindingEdge&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="K"/>
+      <param name="toId" type="K"/>
+      <doc>
+      <![CDATA[Creates a new {@link BindingEdge} instance and adds it to the graph.
+
+ @param fromId Node ID for the interface node.
+ @param toId Node ID for the implementation (class or instance) node.
+ @return The newly created and added {@link BindingEdge}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Factory interface for {@link BindingEdge}s. Renderer implementations will
+ need to provide an implementation for this.
+
+ @param <K> The type for node IDs.
+ @param <T> The {@link BindingEdge} sub-type that this factory provides.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.BindingEdge.Factory -->
+  <!-- start class com.google.inject.grapher.BindingEdge.Type -->
+  <class name="BindingEdge.Type" extends="java.lang.Enum&lt;com.google.inject.grapher.BindingEdge.Type&gt;"
+    abstract="false"
+    static="true" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.BindingEdge.Type[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.BindingEdge.Type"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[Classification for what kind of binding this edge represents.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.BindingEdge.Type -->
+  <!-- start interface com.google.inject.grapher.DependencyEdge -->
+  <interface name="DependencyEdge"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <doc>
+    <![CDATA[Interface for an edge from a class or {@link InjectionPoint} to the
+ interface node that will satisfy the dependency.
+
+ @author phopkins@gmail.com (Pete Hopkins)
+
+ @param <K> The type for node IDs.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.DependencyEdge -->
+  <!-- start interface com.google.inject.grapher.DependencyEdge.Factory -->
+  <interface name="DependencyEdge.Factory"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newDependencyEdge" return="T extends com.google.inject.grapher.DependencyEdge&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="K"/>
+      <param name="fromPoint" type="com.google.inject.spi.InjectionPoint"/>
+      <param name="toId" type="K"/>
+      <doc>
+      <![CDATA[Creates a new {@link DependencyEdge} and adds it to the graph.
+
+ @param fromId The ID for the class or instance node that has the
+     dependency.
+ @param fromPoint The point where the dependency will be
+     {@literal @}{@link Inject}ed. 
+ @param toId The ID for the interface node that satisfies the dependency.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Factory interface for {@link DependencyEdge}s. Renderer implementations
+ will need to provide an implementation for this.
+
+ @param <K> The type for node IDs.
+ @param <T> The {@link DependencyEdge} sub-type that this factory provides.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.DependencyEdge.Factory -->
+  <!-- start class com.google.inject.grapher.GrapherModule -->
+  <class name="GrapherModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GrapherModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Module for the common bindings for {@link InjectorGrapher}. You will also
+ need to bind a {@link Module} that satisfies the {@link Renderer}
+ dependency.
+ <p>
+ If you want to use subtypes of the node and edge classes, or a different
+ node ID type, you will need to override the {@link GraphingVisitor} binding
+ to specify the new type parameters. 
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.GrapherModule -->
+  <!-- start class com.google.inject.grapher.GraphingVisitor -->
+  <class name="GraphingVisitor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;java.lang.Object, java.lang.Void&gt;"/>
+    <constructor name="GraphingVisitor" type="com.google.inject.grapher.NodeIdFactory&lt;K&gt;, com.google.inject.grapher.InterfaceNode.Factory&lt;K, N&gt;, com.google.inject.grapher.ImplementationNode.Factory&lt;K, M&gt;, com.google.inject.grapher.BindingEdge.Factory&lt;K, B&gt;, com.google.inject.grapher.DependencyEdge.Factory&lt;K, D&gt;, com.google.inject.grapher.NodeAliasFactory&lt;K&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getClassNodeId" return="K"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Helper method to return the standard node ID for the {@link Binding}'s
+ {@link Key}.
+ 
+ @see NodeIdFactory#getClassNodeId(Key)]]>
+      </doc>
+    </method>
+    <method name="getInstanceNodeId" return="K"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Helper method to return the instance node ID for the {@link Binding}'s
+ {@link Key}.
+ 
+ @see NodeIdFactory#getInstanceNodeId(Key)]]>
+      </doc>
+    </method>
+    <method name="newInterfaceNode" return="N extends com.google.inject.grapher.InterfaceNode&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Creates and returns a new {@link InterfaceNode} object for the given
+ {@link Binding}.]]>
+      </doc>
+    </method>
+    <method name="newClassImplementationNode" return="M extends com.google.inject.grapher.ImplementationNode&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <param name="constructorInjectionPoint" type="com.google.inject.spi.InjectionPoint"/>
+      <param name="memberInjectionPoints" type="java.util.Collection&lt;com.google.inject.spi.InjectionPoint&gt;"/>
+      <doc>
+      <![CDATA[Creates and returns a new {@link ImplementationNode} for the given
+ {@link Binding}, where the {@link Binding} is for a class that Guice
+ will instantiate, rather than a specific instance.]]>
+      </doc>
+    </method>
+    <method name="newInstanceImplementationNode" return="M extends com.google.inject.grapher.ImplementationNode&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Creates and returns a new {@link ImplementationNode} for the given
+ {@link Binding}, where the {@link Binding} is for an instance, rather than
+ a class.]]>
+      </doc>
+    </method>
+    <method name="newBindingEdge" return="B extends com.google.inject.grapher.BindingEdge&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="nodeId" type="K"/>
+      <param name="toId" type="K"/>
+      <param name="type" type="com.google.inject.grapher.BindingEdge.Type"/>
+      <doc>
+      <![CDATA[Creates a new {@link BindingEdge} from the given node to the specified
+ node.
+
+ @param nodeId ID of the {@link InterfaceNode} that binds to the other.
+ @param toId The node ID of a class or instance that is bound.
+ @param type The {@link BindingEdge.Type} of this binding.
+ @return The newly-created and added {@link BindingEdge}.]]>
+      </doc>
+    </method>
+    <method name="newDependencyEdges" return="java.util.Collection&lt;D&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="nodeId" type="K"/>
+      <param name="node" type="M extends com.google.inject.grapher.ImplementationNode&lt;K&gt;"/>
+      <param name="dependencies" type="java.util.Collection&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"/>
+      <doc>
+      <![CDATA[Adds {@link DependencyEdge}s to the graph for each of the provided
+ {@link Dependency}s. These will be from the given node ID to the
+ {@link Dependency}'s {@link Key}.
+ <p>
+ If a {@link Dependency} has an associated {@link InjectionPoint}, its
+ member will be added to the given {@link ImplementationNode} and the edge
+ will start at the {@link Member}.
+
+ @see #newDependencyEdge(Object, InjectionPoint, Dependency)
+ 
+ @param nodeId ID of the node that should be the tail of the
+     {@link DependencyEdge}s.
+ @param node An {@link ImplementationNode} to add {@link Member}s to.
+ @param dependencies {@link Collection} of {@link Dependency}s from the
+     {@link Binding}.
+ @return A {@link Collection} of the {@link DependencyEdge}s that were
+     added to the graph.]]>
+      </doc>
+    </method>
+    <method name="newDependencyEdge" return="D extends com.google.inject.grapher.DependencyEdge&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="nodeId" type="K"/>
+      <param name="injectionPoint" type="com.google.inject.spi.InjectionPoint"/>
+      <param name="dependency" type="com.google.inject.spi.Dependency&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Creates a new {@link DependencyEdge} from the given node to a
+ {@link Dependency}.
+ <p>
+ This method takes more comprehensive parameters than strictly necessary
+ in case they would be useful to overriding implementations.
+
+ @param nodeId ID of the {@link ImplementationNode} where the edges will start.
+ @param injectionPoint The {@link InjectionPoint} that gave rise to this
+     {@link Dependency}, if one exists. Used to figure out which
+     {@link Member} the edge should point from.
+ @param dependency The {@link Dependency} to represent with this edge.
+ @return The newly-created and added {@link DependencyEdge}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConstructorBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Visitor for {@link ConstructorBinding}s. These are for classes that Guice
+ will instantiate to satisfy injection requests. We create a new
+ {@link ImplementationNode} for the class, then add edges to everything
+ that it depends on to be instantiated.
+
+ @see #newClassImplementationNode(Binding, InjectionPoint, Collection)
+ @see #newDependencyEdges(Object, ImplementationNode, Collection)]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Visitor for {@link ConvertedConstantBinding}. The {@link Binding}'s
+ {@link Key} will be of an annotated primitive type, and the value of
+ {@link ConvertedConstantBinding#getSourceKey()} will be of a
+ {@link String} with the same annotation.
+ <p>
+ We render this as an {@link InterfaceNode} that has a
+ {@link BindingEdge} to the source {@link Key}. That will then be rendered
+ by {@link #visit(InstanceBinding)} as an {@link InterfaceNode}
+ with a {@link BindingEdge} to the {@link String} instance.
+ 
+ @see #newInterfaceNode(Binding)
+ @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type)]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ExposedBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Currently not displayed on the graph.]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InstanceBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Visitor for {@link InstanceBinding}. We render two nodes in this case: a
+ {@link InterfaceNode} for the binding's {@link Key}, and then an
+ {@link ImplementationNode} for the instance {@link Object} itself. We run
+ a binding node between them.
+ <p>
+ We then render any {@link DependencyEdge}s that the instance may have,
+ which come either from {@link InjectionPoint}s (method and field) on the
+ instance, or on {@link Dependency}s the instance declares through the
+ {@link HasDependencies} interface.
+ 
+ @see #newInterfaceNode(Binding)
+ @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type)
+ @see #newInstanceImplementationNode(Binding, Object)
+ @see #newDependencyEdges(Object, ImplementationNode, java.util.Collection)]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Visitor for {@link LinkedKeyBinding}. This is the standard {@link Binding}
+ you get from binding an interface class to an implementation class. We
+ create an {@link InterfaceNode}, then draw a {@link BindingEdge} to the
+ node of the implementing class.
+ 
+ @see #newInterfaceNode(Binding)
+ @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type)]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Visitor for {@link ProviderBinding}. These {@link Binding}s arise from an
+ {@link InjectionPoint} for the {@link Provider} interface. Since this
+ isn't tremendously interesting information, we don't render this binding
+ on the graph, and instead let the {@link DependencyEdge} go straight from
+ the {@link InjectionPoint} to the node specified by
+ {@link ProviderBinding#getProvidedKey()}.
+ 
+ @see NodeAliasFactory#newAlias(Object, Object)]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Same as {@link #visit(InstanceBinding)}, but the
+ {@link BindingEdge} is {@link BindingEdge.Type#PROVIDER}.
+ 
+ @see #newInterfaceNode(Binding)
+ @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type)
+ @see #newInstanceImplementationNode(Binding, Object)
+ @see #newDependencyEdges(Object, ImplementationNode, java.util.Collection)]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Same as {@link #visit(LinkedKeyBinding)}, but the
+ {@link BindingEdge} is {@link BindingEdge.Type#PROVIDER}.
+ 
+ @see #newInterfaceNode(Binding)
+ @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type)]]>
+      </doc>
+    </method>
+    <method name="visit" return="java.lang.Void"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.UntargettedBinding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Currently not displayed on the graph.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[{@link BindingTargetVisitor} that adds nodes and edges to the graph based on
+ the visited {@link Binding}.
+ <p>
+ This class is parameterized over the four graph element types
+ ({@link InterfaceNode}, {@link ImplementationNode}, {@link BindingEdge}, and
+ {@link DependencyEdge}) so that you can extend those interfaces and also
+ extend this class, and the helper methods will all return your new types.
+ 
+ @author phopkins@gmail.com (Pete Hopkins)
+
+ @param <K> The type for node IDs.
+ @param <N> Type for {@link InterfaceNode}s.
+ @param <M> Type for {@link ImplementationNode}.s
+ @param <B> Type for {@link BindingEdge}s.
+ @param <D> Type for {@link DependencyEdge}s.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.GraphingVisitor -->
+  <!-- start interface com.google.inject.grapher.ImplementationNode -->
+  <interface name="ImplementationNode"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="setClassKey"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Sets the {@link Key} that this node is for. Used when the node is
+ representing a class that Guice will instantiate.]]>
+      </doc>
+    </method>
+    <method name="setInstance"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Sets the {@link Object} that's the already-created instance. Used when
+ this node is represeting the instance instead of a class.]]>
+      </doc>
+    </method>
+    <method name="setSource"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <method name="addMember"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <doc>
+    <![CDATA[Node for classes and instances that have {@link Dependency}s and are
+ bound to {@link InterfaceNode}s. These nodes will often have fields for
+ {@link Member}s that are {@link InjectionPoint}s.
+ 
+ @see DependencyEdge
+
+ @author phopkins@gmail.com (Pete Hopkins)
+
+ @param <K> The type for node IDs.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.ImplementationNode -->
+  <!-- start interface com.google.inject.grapher.ImplementationNode.Factory -->
+  <interface name="ImplementationNode.Factory"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newImplementationNode" return="T extends com.google.inject.grapher.ImplementationNode&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="nodeId" type="K"/>
+      <doc>
+      <![CDATA[Creates a new {@link ImplementationNode} and adds it to the graph.
+
+ @param nodeId ID for the node.
+ @return The new {@link ImplementationNode} instance.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Factory interface for {@link ImplementationNode}s. Renderer
+ implementations will need to provide an implementation for this.
+
+ @param <K> The type for node IDs.
+ @param <T> The {@link ImplementationNode} sub-type that this factory
+     provides.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.ImplementationNode.Factory -->
+  <!-- start class com.google.inject.grapher.InjectorGrapher -->
+  <class name="InjectorGrapher" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="InjectorGrapher" type="com.google.inject.spi.BindingTargetVisitor&lt;java.lang.Object, java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;&gt;, com.google.inject.spi.BindingTargetVisitor&lt;java.lang.Object, java.lang.Void&gt;, com.google.inject.grapher.Renderer"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="of" return="com.google.inject.grapher.InjectorGrapher"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Sets the {@link Injector} to graph.]]>
+      </doc>
+    </method>
+    <method name="rootedAt" return="com.google.inject.grapher.InjectorGrapher"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classes" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[Sets an initial group of {@link Class}es to use as the starting point for
+ the graph. The graph will be of these classes and their transitive
+ dependencies and bindings.]]>
+      </doc>
+    </method>
+    <method name="rootedAt" return="com.google.inject.grapher.InjectorGrapher"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="keys" type="com.google.inject.Key[]"/>
+      <doc>
+      <![CDATA[Sets an initial group of {@link Key}s to use as the starting point for
+ the graph. The graph will be of these keys and their transitive
+ dependencies and bindings.]]>
+      </doc>
+    </method>
+    <method name="graph"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Renders a graph with the bound {@link Renderer}. The {@link Injector}
+ must have already been specified with {@link #of(Injector)}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Root class for graphing an {@link Injector}. Bound in {@link GrapherModule}.
+ <p>
+ Use {@link #of(Injector)} to specify the {@link Injector} to use, and
+ {@link graph()} to graph the {@link Injector} using the currently-bound
+ {@link Renderer}.
+ <p>
+ By default, this will graph the entire {@link Injector}. Use
+ {@link #rootedAt(Class...)} or {@link #rootedAt(Key...)} to specify an
+ initial set of {@link Class}es or {@link Key}s to use, and this will graph
+ their transitive bindings and dependencies.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.InjectorGrapher -->
+  <!-- start interface com.google.inject.grapher.InterfaceNode -->
+  <interface name="InterfaceNode"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="setKey"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="setSource"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <doc>
+    <![CDATA[Node for an interface class that has been bound to an implementation class
+ or instance. These nodes are basically defined by a {@link Key}.
+
+ @see BindingEdge
+
+ @author phopkins@gmail.com (Pete Hopkins)
+
+ @param <K> The type for node IDs.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.InterfaceNode -->
+  <!-- start interface com.google.inject.grapher.InterfaceNode.Factory -->
+  <interface name="InterfaceNode.Factory"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newInterfaceNode" return="T extends com.google.inject.grapher.InterfaceNode&lt;K&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="nodeId" type="K"/>
+      <doc>
+      <![CDATA[Creates a new {@link InterfaceNode} and adds it to the graph.
+
+ @param nodeId ID for the node.
+ @return The new {@link InterfaceNode} instance.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Factory interface for {@link InterfaceNode}s. Renderer implementations
+ will need to provide an implementation for this.
+
+ @param <K> The type for node IDs.
+ @param <T> The {@link InterfaceNode} sub-type that this factory provides.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.InterfaceNode.Factory -->
+  <!-- start interface com.google.inject.grapher.NameFactory -->
+  <interface name="NameFactory"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getMemberName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <method name="getClassName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getInstanceName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+    </method>
+    <method name="getAnnotationName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getSourceName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <doc>
+    <![CDATA[Interface for a service that provides nice {@link String}s that we can
+ display in the graph for the types that come up in {@link Binding}s.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.NameFactory -->
+  <!-- start interface com.google.inject.grapher.NodeAliasFactory -->
+  <interface name="NodeAliasFactory"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newAlias"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="K"/>
+      <param name="toId" type="K"/>
+      <doc>
+      <![CDATA[Makes edges that would point to {@code fromId} point to
+ {@code toId} instead.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Factory for aliasing one node ID to another. Used when we don't want to
+ render {@link Key}s from {@link Binding}s that are not interesting.
+ 
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.NodeAliasFactory -->
+  <!-- start interface com.google.inject.grapher.NodeIdFactory -->
+  <interface name="NodeIdFactory"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getClassNodeId" return="K"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getInstanceNodeId" return="K"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[Factory for abstract identifiers for elements on the graph. Most graph nodes
+ will correspond directly to {@link Key}s, but we do this for additional
+ flexibility and because instances do not have separate {@link Key}s from the
+ interfaces they are bound to.
+ <p>
+ Node IDs are treated as opaque values by {@link GraphingVisitor} and the
+ other classes in this package.
+
+ @author phopkins@gmail.com (Pete Hopkins)
+ 
+ @param <K> The type for node IDs.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.NodeIdFactory -->
+  <!-- start interface com.google.inject.grapher.Renderer -->
+  <interface name="Renderer"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="render"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="IOException" type="java.io.IOException"/>
+    </method>
+    <doc>
+    <![CDATA[Interface for the service that renders the graph. It is assumed that the
+ implementations for {@link BindingEdge.Factory},
+ {@link ImplementationNode.Factory}, etc. will have direct access to the
+ internals of the {@link Renderer} implementation, so the only external
+ interface needed is the {@link #render()} call that {@link InjectorGrapher}
+ calls when it's done.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.Renderer -->
+  <!-- start class com.google.inject.grapher.ShortNameFactory -->
+  <class name="ShortNameFactory" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.NameFactory"/>
+    <constructor name="ShortNameFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getMemberName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <method name="getAnnotationName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getClassName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getInstanceName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+    </method>
+    <method name="getSourceName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a name for a Guice "source" object. This will typically be either
+ a {@link StackTraceElement} for when the binding is made to the instance,
+ or a {@link Method} when a provider method is used.]]>
+      </doc>
+    </method>
+    <method name="getFileString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="stackTraceElement" type="java.lang.StackTraceElement"/>
+    </method>
+    <method name="getMethodString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="method" type="java.lang.reflect.Method"/>
+    </method>
+    <doc>
+    <![CDATA[Reasonable implementation for {@link NameFactory}. Mostly takes various
+ {@link Object#toString()}s and strips package names out of them so that
+ they'll fit on the graph.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.ShortNameFactory -->
+  <!-- start class com.google.inject.grapher.StringNodeIdFactory -->
+  <class name="StringNodeIdFactory" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.NodeIdFactory&lt;java.lang.String&gt;"/>
+    <constructor name="StringNodeIdFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getClassNodeId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getInstanceNodeId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[{@link IdFactory} implementation that for {@link String} node IDs. The IDs
+ are comprised of letters, numbers and underscores.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.StringNodeIdFactory -->
+  <!-- start class com.google.inject.grapher.TransitiveDependencyVisitor -->
+  <class name="TransitiveDependencyVisitor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;java.lang.Object, java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;&gt;"/>
+    <constructor name="TransitiveDependencyVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConstructorBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ExposedBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InstanceBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.UntargettedBinding&lt;?&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[{@link BindingTargetVisitor} that returns a {@link Collection} of the
+ {@link Key}s of each {@link Binding}'s dependencies. Used by
+ {@link InjectorGropher} to walk the dependency graph from a starting set of
+ {@link Binding}s.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.TransitiveDependencyVisitor -->
+</package>
+<package name="com.google.inject.grapher.graphviz">
+  <!-- start class com.google.inject.grapher.graphviz.ArrowType -->
+  <class name="ArrowType" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.ArrowType[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.ArrowType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Arrow symbols that are available from Graphviz. These can be composed by
+ concatenation to make double arrows and such.
+ <p>
+ See: http://www.graphviz.org/doc/info/arrows.html
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.ArrowType -->
+  <!-- start class com.google.inject.grapher.graphviz.BindingEdgeFactory -->
+  <class name="BindingEdgeFactory" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.BindingEdge.Factory&lt;java.lang.String, com.google.inject.grapher.BindingEdge&lt;java.lang.String&gt;&gt;"/>
+    <constructor name="BindingEdgeFactory" type="com.google.inject.grapher.graphviz.GraphvizRenderer"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="newBindingEdge" return="com.google.inject.grapher.BindingEdge&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="java.lang.String"/>
+      <param name="toId" type="java.lang.String"/>
+    </method>
+    <method name="newAdaptor" return="com.google.inject.grapher.graphviz.BindingEdgeFactory.GraphvizEdgeAdaptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"/>
+    </method>
+    <doc>
+    <![CDATA[Graphviz-specific implementation of {@link BindingEdge.Factory}. Uses a
+ {@link GraphvizEdgeAdaptor} to delegate to a {@link GraphvizEdge}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.BindingEdgeFactory -->
+  <!-- start class com.google.inject.grapher.graphviz.BindingEdgeFactory.GraphvizEdgeAdaptor -->
+  <class name="BindingEdgeFactory.GraphvizEdgeAdaptor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="protected"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.BindingEdge&lt;java.lang.String&gt;"/>
+    <constructor name="BindingEdgeFactory.GraphvizEdgeAdaptor" type="com.google.inject.grapher.graphviz.GraphvizEdge"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="setType"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.grapher.BindingEdge.Type"/>
+    </method>
+    <field name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"
+      transient="false" volatile="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </field>
+    <doc>
+    <![CDATA[Adaptor class that converts {@link BindingEdge} methods to display
+ operations on a {@link GraphvizEdge}.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.BindingEdgeFactory.GraphvizEdgeAdaptor -->
+  <!-- start class com.google.inject.grapher.graphviz.CompassPoint -->
+  <class name="CompassPoint" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.CompassPoint&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.CompassPoint[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.CompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Enum for the "compass point" values used to control where edge
+ end points appear on the graph.
+ <p>
+ See: http://www.graphviz.org/doc/info/attrs.html#k:portPos
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.CompassPoint -->
+  <!-- start class com.google.inject.grapher.graphviz.DependencyEdgeFactory -->
+  <class name="DependencyEdgeFactory" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.DependencyEdge.Factory&lt;java.lang.String, com.google.inject.grapher.DependencyEdge&lt;java.lang.String&gt;&gt;"/>
+    <constructor name="DependencyEdgeFactory" type="com.google.inject.grapher.graphviz.GraphvizRenderer, com.google.inject.grapher.graphviz.PortIdFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="newDependencyEdge" return="com.google.inject.grapher.DependencyEdge&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="java.lang.String"/>
+      <param name="fromPoint" type="com.google.inject.spi.InjectionPoint"/>
+      <param name="toId" type="java.lang.String"/>
+    </method>
+    <method name="newAdaptor" return="com.google.inject.grapher.graphviz.DependencyEdgeFactory.GraphvizEdgeAdaptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"/>
+    </method>
+    <doc>
+    <![CDATA[Graphviz-specific implementation of {@link DependencyEdge.Factory}. Uses a
+ {@link GraphvizEdgeAdaptor} to delegate to a {@link GraphvizEdge}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.DependencyEdgeFactory -->
+  <!-- start class com.google.inject.grapher.graphviz.DependencyEdgeFactory.GraphvizEdgeAdaptor -->
+  <class name="DependencyEdgeFactory.GraphvizEdgeAdaptor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="protected"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.DependencyEdge&lt;java.lang.String&gt;"/>
+    <constructor name="DependencyEdgeFactory.GraphvizEdgeAdaptor" type="com.google.inject.grapher.graphviz.GraphvizEdge"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <field name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"
+      transient="false" volatile="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </field>
+    <doc>
+    <![CDATA[Adaptor class that converts {@link DependencyEdge} methods to display
+ operations on a {@link GraphvizEdge}.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.DependencyEdgeFactory.GraphvizEdgeAdaptor -->
+  <!-- start class com.google.inject.grapher.graphviz.EdgeStyle -->
+  <class name="EdgeStyle" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.EdgeStyle&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.EdgeStyle[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.EdgeStyle"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Styles for edges.
+ <p>
+ See: http://www.graphviz.org/doc/info/attrs.html#k:style
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.EdgeStyle -->
+  <!-- start class com.google.inject.grapher.graphviz.GraphvizEdge -->
+  <class name="GraphvizEdge" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GraphvizEdge" type="java.lang.String, java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getHeadNodeId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getHeadPortId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setHeadPortId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="headPortId" type="java.lang.String"/>
+    </method>
+    <method name="getHeadCompassPoint" return="com.google.inject.grapher.graphviz.CompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setHeadCompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="headCompassPoint" type="com.google.inject.grapher.graphviz.CompassPoint"/>
+    </method>
+    <method name="getArrowHead" return="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setArrowHead"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="arrowHead" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"/>
+    </method>
+    <method name="getTailNodeId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTailPortId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setTailPortId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="tailPortId" type="java.lang.String"/>
+    </method>
+    <method name="getTailCompassPoint" return="com.google.inject.grapher.graphviz.CompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setTailCompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="tailCompassPoint" type="com.google.inject.grapher.graphviz.CompassPoint"/>
+    </method>
+    <method name="getArrowTail" return="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setArrowTail"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="arrowTail" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"/>
+    </method>
+    <method name="getStyle" return="com.google.inject.grapher.graphviz.EdgeStyle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setStyle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="style" type="com.google.inject.grapher.graphviz.EdgeStyle"/>
+    </method>
+    <doc>
+    <![CDATA[Data object to encapsulate the attributes of Graphviz edges that we're
+ interested in drawing.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.GraphvizEdge -->
+  <!-- start class com.google.inject.grapher.graphviz.GraphvizModule -->
+  <class name="GraphvizModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GraphvizModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Module that provides {@link GraphvizRenderer} as the {@link Renderer} and
+ binds the other Graphviz factories.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.GraphvizModule -->
+  <!-- start class com.google.inject.grapher.graphviz.GraphvizNode -->
+  <class name="GraphvizNode" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GraphvizNode" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getNodeId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getShape" return="com.google.inject.grapher.graphviz.NodeShape"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setShape"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="shape" type="com.google.inject.grapher.graphviz.NodeShape"/>
+    </method>
+    <method name="getStyle" return="com.google.inject.grapher.graphviz.NodeStyle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setStyle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="style" type="com.google.inject.grapher.graphviz.NodeStyle"/>
+    </method>
+    <method name="getTitle" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setTitle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="title" type="java.lang.String"/>
+    </method>
+    <method name="getSubtitles" return="java.util.List&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="addSubtitle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="position" type="int"/>
+      <param name="subtitle" type="java.lang.String"/>
+    </method>
+    <method name="getHeaderTextColor" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setHeaderTextColor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="headerTextColor" type="java.lang.String"/>
+    </method>
+    <method name="getHeaderBackgroundColor" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setHeaderBackgroundColor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="headerBackgroundColor" type="java.lang.String"/>
+    </method>
+    <method name="addField"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="portId" type="java.lang.String"/>
+      <param name="title" type="java.lang.String"/>
+    </method>
+    <method name="getFields" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Data object to encapsulate the attributes of Graphviz nodes that we're
+ interested in drawing.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.GraphvizNode -->
+  <!-- start class com.google.inject.grapher.graphviz.GraphvizRenderer -->
+  <class name="GraphvizRenderer" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.Renderer"/>
+    <implements name="com.google.inject.grapher.NodeAliasFactory&lt;java.lang.String&gt;"/>
+    <constructor name="GraphvizRenderer"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="setOut" return="com.google.inject.grapher.graphviz.GraphvizRenderer"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="out" type="java.io.PrintWriter"/>
+    </method>
+    <method name="setRankdir" return="com.google.inject.grapher.graphviz.GraphvizRenderer"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="rankdir" type="java.lang.String"/>
+    </method>
+    <method name="addNode"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"/>
+    </method>
+    <method name="addEdge"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"/>
+    </method>
+    <method name="newAlias"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="java.lang.String"/>
+      <param name="toId" type="java.lang.String"/>
+    </method>
+    <method name="resolveAlias" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="id" type="java.lang.String"/>
+    </method>
+    <method name="render"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getGraphAttributes" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="start"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="finish"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="renderNode"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"/>
+    </method>
+    <method name="getNodeAttributes" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"/>
+    </method>
+    <method name="getNodeLabel" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"/>
+      <doc>
+      <![CDATA[Creates the "label" for a node. This is a string of HTML that defines a
+ table with a heading at the top and (in the case of
+ {@link ImplementationNode}s) rows for each of the member fields.]]>
+      </doc>
+    </method>
+    <method name="renderEdge"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"/>
+    </method>
+    <method name="getEdgeAttributes" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"/>
+    </method>
+    <method name="getArrowString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="arrows" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"/>
+      <doc>
+      <![CDATA[Turns a {@link List} of {@link ArrowType}s into a {@link String} that
+ represents combining them. With Graphviz, that just means concatenating
+ them.]]>
+      </doc>
+    </method>
+    <method name="getEdgeEndPoint" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="nodeId" type="java.lang.String"/>
+      <param name="portId" type="java.lang.String"/>
+      <param name="compassPoint" type="com.google.inject.grapher.graphviz.CompassPoint"/>
+    </method>
+    <method name="htmlEscape" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="str" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[{@link Renderer} implementation that writes out a Graphviz DOT file of the
+ graph. Bound in {@link GraphvizModule}.
+ <p>
+ Specify the {@link PrintWriter} to output to with
+ {@link #setOut(PrintWriter)}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.GraphvizRenderer -->
+  <!-- start class com.google.inject.grapher.graphviz.ImplementationNodeFactory -->
+  <class name="ImplementationNodeFactory" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.ImplementationNode.Factory&lt;java.lang.String, com.google.inject.grapher.ImplementationNode&lt;java.lang.String&gt;&gt;"/>
+    <constructor name="ImplementationNodeFactory" type="com.google.inject.grapher.graphviz.GraphvizRenderer, com.google.inject.grapher.NameFactory, com.google.inject.grapher.graphviz.PortIdFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="newImplementationNode" return="com.google.inject.grapher.ImplementationNode&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="nodeId" type="java.lang.String"/>
+    </method>
+    <method name="newAdaptor" return="com.google.inject.grapher.graphviz.ImplementationNodeFactory.GraphvizNodeAdaptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"/>
+    </method>
+    <doc>
+    <![CDATA[Graphviz-specific implementation of {@link ImplementationNode.Factory}. Uses
+ a {@link GraphvizEdgeAdaptor} to delegate to a {@link GraphvizNode}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.ImplementationNodeFactory -->
+  <!-- start class com.google.inject.grapher.graphviz.ImplementationNodeFactory.GraphvizNodeAdaptor -->
+  <class name="ImplementationNodeFactory.GraphvizNodeAdaptor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="protected"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.ImplementationNode&lt;java.lang.String&gt;"/>
+    <constructor name="ImplementationNodeFactory.GraphvizNodeAdaptor" type="com.google.inject.grapher.graphviz.GraphvizNode"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="setClassKey"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="setInstance"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+    </method>
+    <method name="setSource"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <method name="addMember"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <field name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"
+      transient="false" volatile="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </field>
+    <doc>
+    <![CDATA[Adaptor class that converts {@link ImplementationNode} methods to display
+ operations on a {@link GraphvizNode}.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.ImplementationNodeFactory.GraphvizNodeAdaptor -->
+  <!-- start class com.google.inject.grapher.graphviz.InterfaceNodeFactory -->
+  <class name="InterfaceNodeFactory" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.InterfaceNode.Factory&lt;java.lang.String, com.google.inject.grapher.InterfaceNode&lt;java.lang.String&gt;&gt;"/>
+    <constructor name="InterfaceNodeFactory" type="com.google.inject.grapher.graphviz.GraphvizRenderer, com.google.inject.grapher.NameFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="newInterfaceNode" return="com.google.inject.grapher.InterfaceNode&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="nodeId" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[Graphviz-specific implementation of {@link InterfaceNode.Factory}. Uses
+ a {@link GraphvizEdgeAdaptor} to delegate to a {@link GraphvizNode}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.InterfaceNodeFactory -->
+  <!-- start class com.google.inject.grapher.graphviz.InterfaceNodeFactory.GraphvizNodeAdaptor -->
+  <class name="InterfaceNodeFactory.GraphvizNodeAdaptor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="protected"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.InterfaceNode&lt;java.lang.String&gt;"/>
+    <constructor name="InterfaceNodeFactory.GraphvizNodeAdaptor" type="com.google.inject.grapher.graphviz.GraphvizNode"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="setKey"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="setSource"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <field name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"
+      transient="false" volatile="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </field>
+    <doc>
+    <![CDATA[Adaptor class that converts {@link InterfaceNode} methods to display
+ operations on a {@link GraphvizNode}.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.InterfaceNodeFactory.GraphvizNodeAdaptor -->
+  <!-- start class com.google.inject.grapher.graphviz.NodeShape -->
+  <class name="NodeShape" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.NodeShape&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.NodeShape[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.NodeShape"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Enum for the shapes that are most interesting for Guice graphing.
+ <p>
+ See: http://www.graphviz.org/doc/info/shapes.html
+ 
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.NodeShape -->
+  <!-- start class com.google.inject.grapher.graphviz.NodeStyle -->
+  <class name="NodeStyle" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.NodeStyle&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.NodeStyle[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.NodeStyle"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Styles for nodes. Similar to {@link EdgeStyle} but with a few more options.
+ <p>
+ See: http://www.graphviz.org/doc/info/attrs.html#k:style
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.NodeStyle -->
+  <!-- start interface com.google.inject.grapher.graphviz.PortIdFactory -->
+  <interface name="PortIdFactory"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getPortId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <doc>
+    <![CDATA[Interface for a service that returns Graphviz port IDs, used for naming the
+ rows in {@link ImplementationNode}-displaying {@link GraphvizNode}s.
+ Implemented by {@link StringNodeIdFactory}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.graphviz.PortIdFactory -->
+  <!-- start class com.google.inject.grapher.graphviz.PortIdFactoryImpl -->
+  <class name="PortIdFactoryImpl" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.graphviz.PortIdFactory"/>
+    <constructor name="PortIdFactoryImpl"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getPortId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <doc>
+    <![CDATA[Implementation of {@link PortIdFactory}. Bound in {@link GraphvizModule}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.PortIdFactoryImpl -->
+</package>
+<package name="com.google.inject.jndi">
+  <!-- start class com.google.inject.jndi.JndiIntegration -->
+  <class name="JndiIntegration" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="fromJndi" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a provider which looks up objects in JNDI using the given name.
+ Example usage:
+
+ <pre>
+ bind(DataSource.class).toProvider(fromJndi(DataSource.class, "java:..."));
+ </pre>]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Integrates Guice with JNDI. Requires a binding to 
+ {@link javax.naming.Context}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.jndi.JndiIntegration -->
+</package>
+<package name="com.google.inject.matcher">
+  <!-- start class com.google.inject.matcher.AbstractMatcher -->
+  <class name="AbstractMatcher" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.matcher.Matcher&lt;T&gt;"/>
+    <constructor name="AbstractMatcher"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="and" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+    </method>
+    <method name="or" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[Implements {@code and()} and {@code or()}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.matcher.AbstractMatcher -->
+  <!-- start interface com.google.inject.matcher.Matcher -->
+  <interface name="Matcher"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="matches" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="T"/>
+      <doc>
+      <![CDATA[Returns {@code true} if this matches {@code t}, {@code false} otherwise.]]>
+      </doc>
+    </method>
+    <method name="and" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new matcher which returns {@code true} if both this and the
+ given matcher return {@code true}.]]>
+      </doc>
+    </method>
+    <method name="or" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new matcher which returns {@code true} if either this or the
+ given matcher return {@code true}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Returns {@code true} or {@code false} for a given input.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.matcher.Matcher -->
+  <!-- start class com.google.inject.matcher.Matchers -->
+  <class name="Matchers" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="any" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a matcher which matches any input.]]>
+      </doc>
+    </method>
+    <method name="not" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="p" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Inverts the given matcher.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches elements (methods, classes, etc.)
+ with a given annotation.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches elements (methods, classes, etc.)
+ with a given annotation.]]>
+      </doc>
+    </method>
+    <method name="subclassesOf" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="superclass" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches subclasses of the given type (as well as
+ the given type).]]>
+      </doc>
+    </method>
+    <method name="only" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches objects equal to the given object.]]>
+      </doc>
+    </method>
+    <method name="identicalTo" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches only the given object.]]>
+      </doc>
+    </method>
+    <method name="inPackage" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetPackage" type="java.lang.Package"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches classes in the given package. Packages are specific to their
+ classloader, so classes with the same package name may not have the same package at runtime.]]>
+      </doc>
+    </method>
+    <method name="inSubpackage" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetPackageName" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches classes in the given package and its subpackages. Unlike
+ {@link #inPackage(Package) inPackage()}, this matches classes from any classloader.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="returns" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.Method&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="returnType" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches methods with matching return types.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Matcher implementations. Supports matching classes and methods.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.matcher.Matchers -->
+</package>
+<package name="com.google.inject.multibindings">
+  <!-- start class com.google.inject.multibindings.MapBinder -->
+  <class name="MapBinder" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="permitDuplicates" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Configures the {@code MapBinder} to handle duplicate entries.
+ <p>When multiple equal keys are bound, the value that gets included in the map is
+ arbitrary.
+ <p>In addition to the {@code Map<K, V>} and {@code Map<K, Provider<V>>}
+ maps that are normally bound, a {@code Map<K, Set<V>>} and
+ {@code Map<K, Set<Provider<V>>>} are <em>also</em> bound, which contain
+ all values bound to each key.
+ <p>
+ When multiple modules contribute elements to the map, this configuration
+ option impacts all of them.
+
+ @return this map binder
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="addBinding" return="com.google.inject.binder.LinkedBindingBuilder&lt;V&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="K"/>
+      <doc>
+      <![CDATA[Returns a binding builder used to add a new entry in the map. Each
+ key must be distinct (and non-null). Bound providers will be evaluated each
+ time the map is injected.
+
+ <p>It is an error to call this method without also calling one of the
+ {@code to} methods on the returned binding builder.
+
+ <p>Scoping elements independently is supported. Use the {@code in} method
+ to specify a binding scope.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An API to bind multiple map entries separately, only to later inject them as
+ a complete map. MapBinder is intended for use in your application's module:
+ <pre><code>
+ public class SnacksModule extends AbstractModule {
+   protected void configure() {
+     MapBinder&lt;String, Snack&gt; mapbinder
+         = MapBinder.newMapBinder(binder(), String.class, Snack.class);
+     mapbinder.addBinding("twix").toInstance(new Twix());
+     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
+     mapbinder.addBinding("skittles").to(Skittles.class);
+   }
+ }</code></pre>
+
+ <p>With this binding, a {@link Map}{@code <String, Snack>} can now be
+ injected:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Map&lt;String, Snack&gt; snacks) { ... }
+ }</code></pre>
+
+ <p>In addition to binding {@code Map<K, V>}, a mapbinder will also bind
+ {@code Map<K, Provider<V>>} for lazy value provision:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Map&lt;String, Provider&lt;Snack&gt;&gt; snackProviders) { ... }
+ }</code></pre>
+
+ <p>Contributing mapbindings from different modules is supported. For example,
+ it is okay to have both {@code CandyModule} and {@code ChipsModule} both
+ create their own {@code MapBinder<String, Snack>}, and to each contribute
+ bindings to the snacks map. When that map is injected, it will contain
+ entries from both modules.
+
+ <p>The map's iteration order is consistent with the binding order. This is
+ convenient when multiple elements are contributed by the same module because
+ that module can order its bindings appropriately. Avoid relying on the
+ iteration order of elements contributed by different modules, since there is
+ no equivalent mechanism to order modules.
+ 
+ <p>The map is unmodifiable.  Elements can only be added to the map by
+ configuring the MapBinder.  Elements can never be removed from the map.
+
+ <p>Values are resolved at map injection time. If a value is bound to a
+ provider, that provider's get method will be called each time the map is
+ injected (unless the binding is also scoped, or a map of providers is injected).
+
+ <p>Annotations are used to create different maps of the same key/value
+ type. Each distinct annotation gets its own independent map.
+
+ <p><strong>Keys must be distinct.</strong> If the same key is bound more than
+ once, map injection will fail. However, use {@link #permitDuplicates()} in
+ order to allow duplicate keys; extra bindings to {@code Map<K, Set<V>>} and
+ {@code Map<K, Set<Provider<V>>} will be added.
+
+ <p><strong>Keys must be non-null.</strong> {@code addBinding(null)} will
+ throw an unchecked exception.
+
+ <p><strong>Values must be non-null to use map injection.</strong> If any
+ value is null, map injection will fail (although injecting a map of providers
+ will not).
+
+ @author dpb@google.com (David P. Baker)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.multibindings.MapBinder -->
+  <!-- start interface com.google.inject.multibindings.MapBinderBinding -->
+  <interface name="MapBinderBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getMapKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the {@link Key} for the map.]]>
+      </doc>
+    </method>
+    <method name="getKeyTypeLiteral" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the TypeLiteral describing the keys of the map.
+ <p>
+ The TypeLiteral will always match the type Map's generic type. For example, if getMapKey
+ returns a key of <code>Map&lt;String, Snack></code>, then this will always return a
+ <code>TypeLiteral&lt;String></code>.]]>
+      </doc>
+    </method>
+    <method name="getValueTypeLiteral" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the TypeLiteral describing the values of the map.
+ <p>
+ The TypeLiteral will always match the type Map's generic type. For example, if getMapKey
+ returns a key of <code>Map&lt;String, Snack></code>, then this will always return a
+ <code>TypeLiteral&lt;Snack></code>.]]>
+      </doc>
+    </method>
+    <method name="getEntries" return="java.util.List&lt;java.util.Map.Entry&lt;?, com.google.inject.Binding&lt;?&gt;&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all entries in the Map. The returned list of Map.Entries contains the key and a binding
+ to the value. Duplicate keys or values will exist as separate Map.Entries in the returned list.
+ This is only supported on bindings returned from an injector. This will throw
+ {@link UnsupportedOperationException} if it is called on an element retrieved from
+ {@link Elements#getElements}.
+ <p>
+ The elements will always match the type Map's generic type. For example, if getMapKey returns a
+ key of <code>Map&lt;String, Snack></code>, then this will always return a list of type
+ <code>List&lt;Map.Entry&lt;String, Binding&lt;Snack>>></code>.]]>
+      </doc>
+    </method>
+    <method name="permitsDuplicates" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if the MapBinder permits duplicates. This is only supported on bindings returned
+ from an injector. This will throw {@link UnsupportedOperationException} if it is called on a
+ MapBinderBinding retrieved from {@link Elements#getElements}.]]>
+      </doc>
+    </method>
+    <method name="containsElement" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="element" type="com.google.inject.spi.Element"/>
+      <doc>
+      <![CDATA[Returns true if this MapBinder contains the given Element in order to build the map or uses the
+ given Element in order to support building and injecting the map. This will work for
+ MapBinderBindings retrieved from an injector and {@link Elements#getElements}. Usually this is
+ only necessary if you are working with elements retrieved from modules (without an Injector),
+ otherwise {@link #getEntries} and {@link #permitsDuplicates} are better options.
+ <p>
+ If you need to introspect the details of the map, such as the keys, values or if it permits
+ duplicates, it is necessary to pass the elements through an Injector and use
+ {@link #getEntries()} and {@link #permitsDuplicates()}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding for a MapBinder.
+ <p>
+ Although MapBinders may be injected through a variety of generic types (Map&lt;K, V>, Map
+ &lt;K, Provider&lt;V>>, Map&lt;K, Set&lt;V>>, Map<K, Set&lt;
+ Provider&lt;V>>, and even Set&lt;Map.Entry&lt;K, Provider&lt;V>>), a
+ MapBinderBinding exists only on the Binding associated with the Map&lt;K, V> key. Other
+ bindings can be validated to be derived from this MapBinderBinding using
+ {@link #containsElement(Element)}.
+ 
+ @param <T> The fully qualified type of the map, including Map. For example:
+          <code>MapBinderBinding&lt;Map&lt;String, Snack>></code>
+ 
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.multibindings.MapBinderBinding -->
+  <!-- start class com.google.inject.multibindings.Multibinder -->
+  <class name="Multibinder" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="permitDuplicates" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Configures the bound set to silently discard duplicate elements. When multiple equal values are
+ bound, the one that gets included is arbitrary. When multiple modules contribute elements to
+ the set, this configuration option impacts all of them.
+
+ @return this multibinder
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="addBinding" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a binding builder used to add a new element in the set. Each
+ bound element must have a distinct value. Bound providers will be
+ evaluated each time the set is injected.
+
+ <p>It is an error to call this method without also calling one of the
+ {@code to} methods on the returned binding builder.
+
+ <p>Scoping elements independently is supported. Use the {@code in} method
+ to specify a binding scope.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An API to bind multiple values separately, only to later inject them as a
+ complete collection. Multibinder is intended for use in your application's
+ module:
+ <pre><code>
+ public class SnacksModule extends AbstractModule {
+   protected void configure() {
+     Multibinder&lt;Snack&gt; multibinder
+         = Multibinder.newSetBinder(binder(), Snack.class);
+     multibinder.addBinding().toInstance(new Twix());
+     multibinder.addBinding().toProvider(SnickersProvider.class);
+     multibinder.addBinding().to(Skittles.class);
+   }
+ }</code></pre>
+
+ <p>With this binding, a {@link Set}{@code <Snack>} can now be injected:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Set&lt;Snack&gt; snacks) { ... }
+ }</code></pre>
+
+ <p>Contributing multibindings from different modules is supported. For
+ example, it is okay to have both {@code CandyModule} and {@code ChipsModule}
+ to both create their own {@code Multibinder<Snack>}, and to each contribute
+ bindings to the set of snacks. When that set is injected, it will contain
+ elements from both modules.
+ 
+ <p>The set's iteration order is consistent with the binding order. This is
+ convenient when multiple elements are contributed by the same module because
+ that module can order its bindings appropriately. Avoid relying on the
+ iteration order of elements contributed by different modules, since there is
+ no equivalent mechanism to order modules.
+ 
+ <p>The set is unmodifiable.  Elements can only be added to the set by
+ configuring the multibinder.  Elements can never be removed from the set.
+
+ <p>Elements are resolved at set injection time. If an element is bound to a
+ provider, that provider's get method will be called each time the set is
+ injected (unless the binding is also scoped).
+
+ <p>Annotations are be used to create different sets of the same element
+ type. Each distinct annotation gets its own independent collection of
+ elements.
+
+ <p><strong>Elements must be distinct.</strong> If multiple bound elements
+ have the same value, set injection will fail.
+
+ <p><strong>Elements must be non-null.</strong> If any set element is null,
+ set injection will fail.
+
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.multibindings.Multibinder -->
+  <!-- start interface com.google.inject.multibindings.MultibinderBinding -->
+  <interface name="MultibinderBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSetKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for the set.]]>
+      </doc>
+    </method>
+    <method name="getElementTypeLiteral" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the TypeLiteral that describes the type of elements in the set.
+ <p>
+ The elements will always match the type Set's generic type. For example, if getSetKey returns a
+ key of <code>Set&lt;String></code>, then this will always return a
+ <code>TypeLiteral&lt;String></code>.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all bindings that make up the set. This is only supported on bindings returned from an
+ injector. This will throw {@link UnsupportedOperationException} if it is called on an element
+ retrieved from {@link Elements#getElements}.
+ <p>
+ The elements will always match the type Set's generic type. For example, if getSetKey returns a
+ key of <code>Set&lt;String></code>, then this will always return a list of type
+ <code>List&lt;Binding&lt;String>></code>.]]>
+      </doc>
+    </method>
+    <method name="permitsDuplicates" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if the multibinder permits duplicates. This is only supported on bindings returned
+ from an injector. This will throw {@link UnsupportedOperationException} if it is called on a
+ MultibinderBinding retrieved from {@link Elements#getElements}.]]>
+      </doc>
+    </method>
+    <method name="containsElement" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="element" type="com.google.inject.spi.Element"/>
+      <doc>
+      <![CDATA[Returns true if this Multibinder uses the given Element. This will be true for bindings that
+ derive the elements of the set and other bindings that Multibinder uses internally. This will
+ work for MultibinderBindings retrieved from an injector and {@link Elements#getElements}.
+ Usually this is only necessary if you are working with elements retrieved from modules (without
+ an Injector), otherwise {@link #getElements} and {@link #permitsDuplicates} are better options.
+ <p>
+ If you need to introspect the details of the set, such as the values or if it permits
+ duplicates, it is necessary to pass the elements through an Injector and use
+ {@link #getElements()} and {@link #permitsDuplicates()}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding for a Multibinder.
+ 
+ @param <T> The fully qualified type of the set, including Set. For example:
+          <code>MultibinderBinding&lt;Set&lt;Boolean>></code>
+ 
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.multibindings.MultibinderBinding -->
+  <!-- start interface com.google.inject.multibindings.MultibindingsTargetVisitor -->
+  <interface name="MultibindingsTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="multibinding" type="com.google.inject.multibindings.MultibinderBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visits a binding created through {@link Multibinder}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="mapbinding" type="com.google.inject.multibindings.MapBinderBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visits a binding created through {@link MapBinder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A visitor for the multibinder extension.
+ <p>
+ If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ {@link Multibinder} or {@link MapBinder} will be visited through this interface.
+ 
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.multibindings.MultibindingsTargetVisitor -->
+</package>
+<package name="com.google.inject.name">
+  <!-- start class com.google.inject.name.Named -->
+  <class name="Named"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates named things.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.name.Named -->
+  <!-- start class com.google.inject.name.Names -->
+  <class name="Names" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="named" return="com.google.inject.name.Named"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a {@link Named} annotation with {@code name} as the value.]]>
+      </doc>
+    </method>
+    <method name="bindProperties"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="properties" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+      <doc>
+      <![CDATA[Creates a constant binding to {@code @Named(key)} for each entry in
+ {@code properties}.]]>
+      </doc>
+    </method>
+    <method name="bindProperties"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="properties" type="java.util.Properties"/>
+      <doc>
+      <![CDATA[Creates a constant binding to {@code @Named(key)} for each property. This
+ method binds all properties including those inherited from 
+ {@link Properties#defaults defaults}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Utility methods for use with {@code @}{@link Named}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.name.Names -->
+</package>
+<package name="com.google.inject.persist">
+  <!-- start class com.google.inject.persist.PersistFilter -->
+  <class name="PersistFilter" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="PersistFilter" type="com.google.inject.persist.UnitOfWork, com.google.inject.persist.PersistService"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="init"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterConfig" type="FilterConfig"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="destroy"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="doFilter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletRequest" type="ServletRequest"/>
+      <param name="servletResponse" type="ServletResponse"/>
+      <param name="filterChain" type="FilterChain"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <doc>
+    <![CDATA[Apply this filter to enable the HTTP Request unit of work and to have
+ guice-persist manage the lifecycle of active units of work.
+ The filter automatically starts and stops the relevant {@link PersistService}
+ upon {@link javax.servlet.Filter#init(javax.servlet.FilterConfig)} and
+ {@link javax.servlet.Filter#destroy()} respectively.
+
+ <p> To be able to use the open session-in-view pattern (i.e. work per request),
+ register this filter <b>once</b> in your Guice {@code ServletModule}. It is
+ important that you register this filter before any other filter.
+
+ For multiple providers, you should register this filter once per provider, inside
+ a private module for each persist module installed (this must be the same private
+ module where the specific persist module is itself installed).
+
+ <p>
+ Example configuration:
+ <pre>{@code
+  public class MyModule extends ServletModule {
+    public void configureServlets() {
+      filter("/*").through(PersistFilter.class);
+
+      serve("/index.html").with(MyHtmlServlet.class);
+      // Etc.
+    }
+  }
+ }</pre>
+ <p>
+ This filter is thread safe and allows you to create injectors concurrently
+ and deploy multiple guice-persist modules within the same injector, or even
+ multiple injectors with persist modules withing the same JVM or web app.
+ <p>
+ This filter requires the Guice Servlet extension.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.PersistFilter -->
+  <!-- start class com.google.inject.persist.PersistModule -->
+  <class name="PersistModule" extends="com.google.inject.AbstractModule"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="PersistModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="configurePersistence"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTransactionInterceptor" return="org.aopalliance.intercept.MethodInterceptor"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Install this module to add guice-persist library support for JPA persistence
+ providers.
+
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.PersistModule -->
+  <!-- start interface com.google.inject.persist.PersistService -->
+  <interface name="PersistService"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="start"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Starts the underlying persistence engine and makes guice-persist ready for
+ use. For instance, with JPA, it creates an EntityManagerFactory and may
+ open connection pools. This method must be called by your code prior to
+ using any guice-persist or JPA artifacts. If already started,
+ calling this method does nothing, if already stopped, it also does
+ nothing.]]>
+      </doc>
+    </method>
+    <method name="stop"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Stops the underlying persistence engine. For instance, with JPA, it
+ closes the {@code EntityManagerFactory}. If already stopped, calling this
+ method does nothing. If not yet started, it also does nothing.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Persistence provider service. Use this to manage the overall
+ startup and stop of the persistence module(s).
+
+ TODO(dhanji): Integrate with Service API when appropriate.
+
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.persist.PersistService -->
+  <!-- start class com.google.inject.persist.Transactional -->
+  <class name="Transactional"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[<p> Any method or class marked with this annotation will be considered for transactionality.
+ Consult the documentation on http://code.google.com/p/google-guice for detailed semantics.
+ Marking a method {@code @Transactional} will start a new transaction before the method
+ executes and commit it after the method returns.
+ <p>
+ If the method throws an exception, the transaction will be rolled back <em>unless</em>
+ you have specifically requested not to in the {@link #ignore()} clause.
+ <p>
+ Similarly, the set of exceptions that will trigger a rollback can be defined in
+ the {@link #rollbackOn()} clause. By default, only unchecked exceptions trigger a
+ rollback.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.Transactional -->
+  <!-- start interface com.google.inject.persist.UnitOfWork -->
+  <interface name="UnitOfWork"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="begin"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Starts a Unit Of Work. Underneath, causes a session to the data layer to be opened. If there
+ is already one open, the invocation will do nothing. In this way, you can define arbitrary
+ units-of-work that nest within one another safely.
+
+ Transaction semantics are not affected.]]>
+      </doc>
+    </method>
+    <method name="end"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Declares an end to the current Unit of Work. Underneath, causes any open session to the data
+ layer to close. If there is no Unit of work open, then the call returns silently. You can
+ safely invoke end() repeatedly.
+ <p>
+ Transaction semantics are not affected.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[This interface is used to gain manual control over the unit of work. This is mostly to do
+ work in non-request, non-transactional threads. Or where more fine-grained control over the unit
+ of work is required. Starting and ending a unit of work directly corresponds to opening and
+ closing a {@code Session}, {@code EntityManager} or {@code ObjectContainer} respectively.
+ <p> The
+ Unit of Work referred to by UnitOfWork will always be local to the calling thread. Be careful to
+ end() in a finally block. Neither JPA, nor Hibernate supports threadsafe sessions (reasoning
+ behind thread-locality of Unit of Work semantics).
+
+ <ul>
+   <li>Using UnitOfWork with the PersistFilter inside a request is not recommended.</li>
+   <li>Using UnitOfWork with session-per-txn strategy is not terribly clever either.</li>
+   <li>Using UnitOfWork with session-per-request strategy but *outside* a request (i.e. in a
+       background or bootstrap thread) is probably a good use case.</li>
+  </ul>
+
+ @author Dhanji R. Prasanna (dhanji@gmail com)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.persist.UnitOfWork -->
+</package>
+<package name="com.google.inject.persist.finder">
+  <!-- start class com.google.inject.persist.finder.DynamicFinder -->
+  <class name="DynamicFinder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="DynamicFinder" type="java.lang.reflect.Method"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="from" return="com.google.inject.persist.finder.DynamicFinder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="method" type="java.lang.reflect.Method"/>
+      <doc>
+      <![CDATA[Returns some metadata if the method is annotated {@code @Finder} or null.
+
+ @param method a method you want to test as a dynamic finder]]>
+      </doc>
+    </method>
+    <method name="metadata" return="com.google.inject.persist.finder.Finder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Utility that helps you introspect dynamic finder methods.
+
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.finder.DynamicFinder -->
+  <!-- start class com.google.inject.persist.finder.Finder -->
+  <class name="Finder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Marks a method stub as a dynamic finder. The method is intercepted and replaced with the
+ specified JPAQL query. Provides result auto-boxing and automatic parameter binding.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.finder.Finder -->
+  <!-- start class com.google.inject.persist.finder.FirstResult -->
+  <class name="FirstResult"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotate any dynamic finder method's integer argument with this to pass in
+ the index of the first result in the result set you are interested in.
+ Useful for paging result sets. Complemented by {@link MaxResults}.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.finder.FirstResult -->
+  <!-- start class com.google.inject.persist.finder.MaxResults -->
+  <class name="MaxResults"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotate any dynamic finder method's integer argument with this to pass in
+ the maximum size of returned result window. Usefule for paging result sets.
+ Complement of {@link FirstResult}.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.finder.MaxResults -->
+</package>
+<package name="com.google.inject.persist.jpa">
+  <!-- start class com.google.inject.persist.jpa.JpaPersistModule -->
+  <class name="JpaPersistModule" extends="com.google.inject.persist.PersistModule"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="JpaPersistModule" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configurePersistence"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTransactionInterceptor" return="org.aopalliance.intercept.MethodInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="properties" return="com.google.inject.persist.jpa.JpaPersistModule"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="properties" type="java.util.Properties"/>
+      <doc>
+      <![CDATA[Configures the JPA persistence provider with a set of properties.
+ 
+ @param properties A set of name value pairs that configure a JPA persistence
+ provider as per the specification.]]>
+      </doc>
+    </method>
+    <method name="addFinder" return="com.google.inject.persist.jpa.JpaPersistModule"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="iface" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Adds an interface to this module to use as a dynamic finder.
+
+ @param iface Any interface type whose methods are all dynamic finders.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[JPA provider for guice persist.
+
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.jpa.JpaPersistModule -->
+</package>
+<package name="com.google.inject.servlet">
+  <!-- start class com.google.inject.servlet.GuiceFilter -->
+  <class name="GuiceFilter" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceFilter"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="doFilter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletRequest" type="ServletRequest"/>
+      <param name="servletResponse" type="ServletResponse"/>
+      <param name="filterChain" type="FilterChain"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="init"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterConfig" type="FilterConfig"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="destroy"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[<p>
+ Apply this filter in web.xml above all other filters (typically), to all requests where you plan
+  to use servlet scopes. This is also needed in order to dispatch requests to injectable filters
+  and servlets:
+  <pre>
+  &lt;filter&gt;
+    &lt;filter-name&gt;guiceFilter&lt;/filter-name&gt;
+    &lt;filter-class&gt;<b>com.google.inject.servlet.GuiceFilter</b>&lt;/filter-class&gt;
+  &lt;/filter&gt;
+
+  &lt;filter-mapping&gt;
+    &lt;filter-name&gt;guiceFilter&lt;/filter-name&gt;
+    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+  &lt;/filter-mapping&gt;
+  </pre>
+
+ This filter must appear before every filter that makes use of Guice injection or servlet
+ scopes functionality. Typically, you will only register this filter in web.xml and register
+ any other filters (and servlets) using a {@link ServletModule}.
+
+ @author crazybob@google.com (Bob Lee)
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.GuiceFilter -->
+  <!-- start class com.google.inject.servlet.GuiceServletContextListener -->
+  <class name="GuiceServletContextListener" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceServletContextListener"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="contextInitialized"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletContextEvent" type="ServletContextEvent"/>
+    </method>
+    <method name="contextDestroyed"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletContextEvent" type="ServletContextEvent"/>
+    </method>
+    <method name="getInjector" return="com.google.inject.Injector"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Override this method to create (or otherwise obtain a reference to) your
+ injector.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[As of Guice 2.0 you can still use (your subclasses of) {@code GuiceServletContextListener}
+ class as a logical place to create and configure your injector. This will ensure the injector
+ is created when the web application is deployed.
+ 
+ @author Kevin Bourrillion (kevinb@google.com)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.GuiceServletContextListener -->
+  <!-- start interface com.google.inject.servlet.InstanceFilterBinding -->
+  <interface name="InstanceFilterBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.servlet.ServletModuleBinding"/>
+    <method name="getFilterInstance" return="Filter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the filter instance that will be used.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a single instance of a filter. 
+
+ @author sameb@google.com
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.InstanceFilterBinding -->
+  <!-- start interface com.google.inject.servlet.InstanceServletBinding -->
+  <interface name="InstanceServletBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.servlet.ServletModuleBinding"/>
+    <method name="getServletInstance" return="HttpServlet"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the servlet instance that will be used.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a single instance of a servlet. 
+
+ @author sameb@google.com
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.InstanceServletBinding -->
+  <!-- start interface com.google.inject.servlet.LinkedFilterBinding -->
+  <interface name="LinkedFilterBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.servlet.ServletModuleBinding"/>
+    <method name="getLinkedKey" return="com.google.inject.Key&lt;? extends Filter&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key used to lookup the filter instance.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A linked binding to a filter. 
+
+ @author sameb@google.com
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.LinkedFilterBinding -->
+  <!-- start interface com.google.inject.servlet.LinkedServletBinding -->
+  <interface name="LinkedServletBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.servlet.ServletModuleBinding"/>
+    <method name="getLinkedKey" return="com.google.inject.Key&lt;? extends HttpServlet&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key used to lookup the servlet instance.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A linked binding to a servlet. 
+
+ @author sameb@google.com
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.LinkedServletBinding -->
+  <!-- start class com.google.inject.servlet.RequestParameters -->
+  <class name="RequestParameters"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to field or parameters of type {@code Map<String, String[]>}
+ when you want the HTTP request parameter map to be injected.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.RequestParameters -->
+  <!-- start class com.google.inject.servlet.RequestScoped -->
+  <class name="RequestScoped"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want one instance per request.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.RequestScoped -->
+  <!-- start class com.google.inject.servlet.ServletModule -->
+  <class name="ServletModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ServletModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="configureServlets"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[<h3>Servlet Mapping EDSL</h3>
+
+ <p> Part of the EDSL builder language for configuring servlets
+ and filters with guice-servlet. Think of this as an in-code replacement for web.xml.
+ Filters and servlets are configured here using simple java method calls. Here is a typical
+ example of registering a filter when creating your Guice injector:
+
+ <pre>
+   Guice.createInjector(..., new ServletModule() {
+
+     {@literal @}Override
+     protected void configureServlets() {
+       <b>serve("*.html").with(MyServlet.class)</b>
+     }
+   }
+ </pre>
+
+ This registers a servlet (subclass of {@code HttpServlet}) called {@code MyServlet} to service
+ any web pages ending in {@code .html}. You can also use a path-style syntax to register
+ servlets:
+
+ <pre>
+       <b>serve("/my/*").with(MyServlet.class)</b>
+ </pre>
+
+ Every servlet (or filter) is required to be a singleton. If you cannot annotate the class
+ directly, you should add a separate {@code bind(..).in(Singleton.class)} rule elsewhere in
+ your module. Mapping a servlet that is bound under any other scope is an error.
+
+ <p>
+ <h4>Dispatch Order</h4>
+ You are free to register as many servlets and filters as you like this way. They will
+ be compared and dispatched in the order in which the filter methods are called:
+
+ <pre>
+
+   Guice.createInjector(..., new ServletModule() {
+
+     {@literal @}Override
+     protected void configureServlets() {
+       filter("/*").through(MyFilter.class);
+       filter("*.css").through(MyCssFilter.class);
+       filter("*.jpg").through(new MyJpgFilter());
+       // etc..
+
+       serve("*.html").with(MyServlet.class);
+       serve("/my/*").with(MyServlet.class);
+       serve("*.jpg").with(new MyServlet());
+       // etc..
+      }
+    }
+ </pre>
+ This will traverse down the list of rules in lexical order. For example, a url
+  "{@code /my/file.js}" (after it runs through the matching filters) will first
+  be compared against the servlet mapping:
+ 
+ <pre>
+       serve("*.html").with(MyServlet.class);
+ </pre>
+ And failing that, it will descend to the next servlet mapping:
+
+ <pre>
+       serve("/my/*").with(MyServlet.class);
+ </pre>
+
+ Since this rule matches, Guice Servlet will dispatch to {@code MyServlet}. These
+ two mapping rules can also be written in more compact form using varargs syntax:
+
+ <pre>
+       serve(<b>"*.html", "/my/*"</b>).with(MyServlet.class);
+ </pre>
+ 
+ This way you can map several URI patterns to the same servlet. A similar syntax is
+ also available for filter mappings.
+
+ <p>
+ <h4>Regular Expressions</h4>
+ You can also map servlets (or filters) to URIs using regular expressions:
+ <pre>
+    <b>serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)</b>
+ </pre>
+
+ This will map any URI containing the text "ajax" in it to {@code MyAjaxServlet}. Such as:
+ <ul>
+ <li>http://www.google.com/ajax.html</li>
+ <li>http://www.google.com/content/ajax/index</li>
+ <li>http://www.google.com/it/is_totally_ajaxian</li>
+ </ul>
+
+
+ <h3>Initialization Parameters</h3>
+
+ Servlets (and filters) allow you to pass in init params
+ using the {@code <init-param>} tag in web.xml. You can similarly pass in parameters to
+ Servlets and filters registered in Guice-servlet using a {@link java.util.Map} of parameter
+ name/value pairs. For example, to initialize {@code MyServlet} with two parameters
+ ({@code name="Dhanji", site="google.com"}) you could write:
+
+ <pre>
+  Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
+  params.put("name", "Dhanji");
+  params.put("site", "google.com");
+
+  ...
+      serve("/*").with(MyServlet.class, <b>params</b>)
+ </pre>
+
+ <p>
+ <h3>Binding Keys</h3>
+
+ You can also bind keys rather than classes. This lets you hide
+ implementations with package-local visbility and expose them using
+ only a Guice module and an annotation:
+
+ <pre>
+  ...
+      filter("/*").through(<b>Key.get(Filter.class, Fave.class)</b>);
+ </pre>
+
+ Where {@code Filter.class} refers to the Servlet API interface and {@code Fave.class} is a
+ custom binding annotation. Elsewhere (in one of your own modules) you can bind this
+ filter's implementation:
+
+ <pre>
+   bind(Filter.class)<b>.annotatedWith(Fave.class)</b>.to(MyFilterImpl.class);
+ </pre>
+
+ See {@link com.google.inject.Binder} for more information on binding syntax.
+
+ <p>
+ <h3>Multiple Modules</h3>
+
+ It is sometimes useful to capture servlet and filter mappings from multiple different
+ modules. This is essential if you want to package and offer drop-in Guice plugins that
+ provide servlet functionality.
+
+ <p>
+ Guice Servlet allows you to register several instances of {@code ServletModule} to your
+ injector. The order in which these modules are installed determines the dispatch order
+ of filters and the precedence order of servlets. For example, if you had two servlet modules,
+ {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped
+ to the same URI pattern, {@code "/*"}:
+
+ <p>
+ In {@code RpcModule}:
+ <pre>
+     filter("/*").through(RpcFilter.class);
+ </pre>
+
+ In {@code WebServiceModule}:
+ <pre>
+     filter("/*").through(WebServiceFilter.class);
+ </pre>
+
+ Then the order in which these filters are dispatched is determined by the order in which
+ the modules are installed:
+
+ <pre>
+   <b>install(new WebServiceModule());</b>
+   install(new RpcModule());
+ </pre>
+
+ In the case shown above {@code WebServiceFilter} will run first.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="filter" return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="urlPattern" type="java.lang.String"/>
+      <param name="morePatterns" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="filterRegex" return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="regex" type="java.lang.String"/>
+      <param name="regexes" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param regex Any Java-style regular expression.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="serve" return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="urlPattern" type="java.lang.String"/>
+      <param name="morePatterns" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="serveRegex" return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="regex" type="java.lang.String"/>
+      <param name="regexes" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param regex Any Java-style regular expression.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getServletContext" return="ServletContext"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[This method only works if you are using the {@linkplain GuiceServletContextListener} to
+ create your injector. Otherwise, it returns null.
+ @return The current servlet context.
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Configures the servlet scopes and creates bindings for the servlet API
+ objects so you can inject the request, response, session, etc.
+
+ <p>
+ You should subclass this module to register servlets and
+ filters in the {@link #configureServlets()} method.
+
+ @author crazybob@google.com (Bob Lee)
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ServletModule -->
+  <!-- start interface com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder -->
+  <interface name="ServletModule.FilterKeyBindingBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;"/>
+    </method>
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;"/>
+    </method>
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filter" type="Filter"/>
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </method>
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="through"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filter" type="Filter"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link ServletModule#configureServlets()}
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder -->
+  <!-- start interface com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder -->
+  <interface name="ServletModule.ServletKeyBindingBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;"/>
+    </method>
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;"/>
+    </method>
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servlet" type="HttpServlet"/>
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </method>
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="with"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servlet" type="HttpServlet"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link ServletModule#configureServlets()}
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder -->
+  <!-- start interface com.google.inject.servlet.ServletModuleBinding -->
+  <interface name="ServletModuleBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getUriPatternType" return="com.google.inject.servlet.UriPatternType"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the pattern type that this binding was created with.]]>
+      </doc>
+    </method>
+    <method name="getPattern" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the pattern used to match against the binding.]]>
+      </doc>
+    </method>
+    <method name="getInitParams" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns any context params supplied when creating the binding.]]>
+      </doc>
+    </method>
+    <method name="matchesUri" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="uri" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Returns true if the given URI will match this binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding created by {@link ServletModule}.
+ 
+ @author sameb@google.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModuleBinding -->
+  <!-- start interface com.google.inject.servlet.ServletModuleTargetVisitor -->
+  <interface name="ServletModuleTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.servlet.LinkedFilterBinding"/>
+      <doc>
+      <![CDATA[Visits a filter binding created by {@link ServletModule#filter}, where
+ {@link FilterKeyBindingBuilder#through} is called with a Class or Key.
+ 
+ If multiple patterns were specified, this will be called multiple times.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.servlet.InstanceFilterBinding"/>
+      <doc>
+      <![CDATA[Visits a filter binding created by {@link ServletModule#filter} where
+ {@link FilterKeyBindingBuilder#through} is called with a {@link Filter}.
+ 
+ If multiple patterns were specified, this will be called multiple times.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.servlet.LinkedServletBinding"/>
+      <doc>
+      <![CDATA[Visits a servlet binding created by {@link ServletModule#serve} where
+ {@link ServletKeyBindingBuilder#with}, is called with a Class or Key.
+ 
+ If multiple patterns were specified, this will be called multiple times.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.servlet.InstanceServletBinding"/>
+      <doc>
+      <![CDATA[Visits a servlet binding created by {@link ServletModule#serve} where 
+ {@link ServletKeyBindingBuilder#with}, is called with an {@link HttpServlet}.
+ 
+ If multiple patterns were specified, this will be called multiple times.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A visitor for the servlet extension.
+ 
+ If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ {@link ServletModule} will be visited through this interface.
+ 
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModuleTargetVisitor -->
+  <!-- start class com.google.inject.servlet.ServletScopes -->
+  <class name="ServletScopes" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="continueRequest" return="java.util.concurrent.Callable&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="callable" type="java.util.concurrent.Callable&lt;T&gt;"/>
+      <param name="seedMap" type="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, java.lang.Object&gt;"/>
+      <doc>
+      <![CDATA[Wraps the given callable in a contextual callable that "continues" the
+ HTTP request in another thread. This acts as a way of transporting
+ request context data from the request processing thread to to worker
+ threads.
+ <p>
+ There are some limitations:
+ <ul>
+   <li>Derived objects (i.e. anything marked @RequestScoped will not be
+      transported.</li>
+   <li>State changes to the HttpServletRequest after this method is called
+      will not be seen in the continued thread.</li>
+   <li>Only the HttpServletRequest, ServletContext and request parameter
+      map are available in the continued thread. The response and session
+      are not available.</li>
+ </ul>
+
+ @param callable code to be executed in another thread, which depends on
+     the request scope.
+ @param seedMap the initial set of scoped instances for Guice to seed the
+     request scope with.  To seed a key with null, use {@code null} as
+     the value.
+ @return a callable that will invoke the given callable, making the request
+     context available to it.
+ @throws OutOfScopeException if this method is called from a non-request
+     thread, or if the request has completed.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="scopeRequest" return="java.util.concurrent.Callable&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="callable" type="java.util.concurrent.Callable&lt;T&gt;"/>
+      <param name="seedMap" type="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, java.lang.Object&gt;"/>
+      <doc>
+      <![CDATA[Scopes the given callable inside a request scope. This is not the same
+ as the HTTP request scope, but is used if no HTTP request scope is in
+ progress. In this way, keys can be scoped as @RequestScoped and exist
+ in non-HTTP requests (for example: RPC requests) as well as in HTTP
+ request threads.
+
+ @param callable code to be executed which depends on the request scope.
+     Typically in another thread, but not necessarily so.
+ @param seedMap the initial set of scoped instances for Guice to seed the
+     request scope with.  To seed a key with null, use {@code null} as
+     the value.
+ @return a callable that when called will run inside the a request scope
+     that exposes the instances in the {@code seedMap} as scoped keys.
+ @since 3.0]]>
+      </doc>
+    </method>
+    <field name="REQUEST" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[HTTP servlet request scope.]]>
+      </doc>
+    </field>
+    <field name="SESSION" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[HTTP session scope.]]>
+      </doc>
+    </field>
+    <doc>
+    <![CDATA[Servlet scopes.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ServletScopes -->
+  <!-- start class com.google.inject.servlet.SessionScoped -->
+  <class name="SessionScoped"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want one instance per session.
+
+ @see com.google.inject.Scopes#SINGLETON
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.SessionScoped -->
+  <!-- start class com.google.inject.servlet.UriPatternType -->
+  <class name="UriPatternType" extends="java.lang.Enum&lt;com.google.inject.servlet.UriPatternType&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.servlet.UriPatternType[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.servlet.UriPatternType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[An enumeration of the available URI-pattern matching styles
+ 
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.UriPatternType -->
+</package>
+<package name="com.google.inject.spi">
+  <!-- start interface com.google.inject.spi.BindingScopingVisitor -->
+  <interface name="BindingScopingVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visitEagerSingleton" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Visit an eager singleton or single instance. This scope strategy is found on both module and
+ injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visitScope" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[Visit a scope instance. This scope strategy is found on both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visitScopeAnnotation" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Visit a scope annotation. This scope strategy is found only on module bindings. The instance
+ that implements this scope is registered by {@link com.google.inject.Binder#bindScope(Class,
+ Scope) Binder.bindScope()}.]]>
+      </doc>
+    </method>
+    <method name="visitNoScoping" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Visit an unspecified or unscoped strategy. On a module, this strategy indicates that the
+ injector should use scoping annotations to find a scope. On an injector, it indicates that
+ no scope is applied to the binding. An unscoped binding will behave like a scoped one when it
+ is linked to a scoped binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visits each of the strategies used to scope an injection.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.BindingScopingVisitor -->
+  <!-- start interface com.google.inject.spi.BindingTargetVisitor -->
+  <interface name="BindingTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a instance binding. The same instance is returned for every injection. This target is
+ found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a provider instance binding. The provider's {@code get} method is invoked to resolve
+ injections. This target is found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a provider key binding. To resolve injections, the provider key is first resolved, then
+ that provider's {@code get} method is invoked. This target is found in both module and injector
+ bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a linked key binding. The other key's binding is used to resolve injections. This
+ target is found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding to a key exposed from an enclosed private environment. This target is only
+ found in injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit an untargetted binding. This target is found only on module bindings. It indicates
+ that the injector should use its implicit binding strategies to resolve injections.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a constructor binding. To resolve injections, an instance is instantiated by invoking
+ {@code constructor}. This target is found only on injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding created from converting a bound instance to a new type. The source binding
+ has the same binding annotation but a different type. This target is found only on injector
+ bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding to a {@link com.google.inject.Provider} that delegates to the binding for the
+ provided type. This target is found only on injector bindings.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visits each of the strategies used to find an instance to satisfy an injection.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.BindingTargetVisitor -->
+  <!-- start interface com.google.inject.spi.ConstructorBinding -->
+  <interface name="ConstructorBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getConstructor" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the constructor this binding injects.]]>
+      </doc>
+    </method>
+    <method name="getInjectableMembers" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.]]>
+      </doc>
+    </method>
+    <method name="getMethodInterceptors" return="java.util.Map&lt;java.lang.reflect.Method, java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the interceptors applied to each method, in the order that they will be applied.
+
+ @return a possibly empty map]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to the constructor of a concrete clss. To resolve injections, an instance is
+ instantiated by invoking the constructor.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ConstructorBinding -->
+  <!-- start interface com.google.inject.spi.ConvertedConstantBinding -->
+  <interface name="ConvertedConstantBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getValue" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the converted value.]]>
+      </doc>
+    </method>
+    <method name="getTypeConverterBinding" return="com.google.inject.spi.TypeConverterBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the type converter binding used to convert the constant.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="getSourceKey" return="com.google.inject.Key&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for the source binding. That binding can e retrieved from an injector using
+ {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.]]>
+      </doc>
+    </method>
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a singleton set containing only the converted key.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding created from converting a bound instance to a new type. The source binding has the same
+ binding annotation but a different type.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ConvertedConstantBinding -->
+  <!-- start class com.google.inject.spi.DefaultBindingScopingVisitor -->
+  <class name="DefaultBindingScopingVisitor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;"/>
+    <constructor name="DefaultBindingScopingVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visitEagerSingleton" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="visitScope" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+    </method>
+    <method name="visitScopeAnnotation" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+    </method>
+    <method name="visitNoScoping" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to
+ {@link #visitOther()}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ 
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultBindingScopingVisitor -->
+  <!-- start class com.google.inject.spi.DefaultBindingTargetVisitor -->
+  <class name="DefaultBindingTargetVisitor" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <constructor name="DefaultBindingTargetVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instanceBinding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerInstanceBinding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerKeyBinding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="linkedKeyBinding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="exposedBinding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="untargettedBinding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructorBinding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="convertedConstantBinding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerBinding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to {@link
+ #visitOther(Binding)}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultBindingTargetVisitor -->
+  <!-- start class com.google.inject.spi.DefaultElementVisitor -->
+  <class name="DefaultElementVisitor" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.ElementVisitor&lt;V&gt;"/>
+    <constructor name="DefaultElementVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="element" type="com.google.inject.spi.Element"/>
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorBinding" type="com.google.inject.spi.InterceptorBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeBinding" type="com.google.inject.spi.ScopeBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeConverterBinding" type="com.google.inject.spi.TypeConverterBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerLookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectionRequest" type="com.google.inject.spi.InjectionRequest&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="staticInjectionRequest" type="com.google.inject.spi.StaticInjectionRequest"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="privateElements" type="com.google.inject.spi.PrivateElements"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeListenerBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.DisableCircularProxiesOption"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.RequireExplicitBindingsOption"/>
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to
+ {@link #visitOther(Element)}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+
+ @author sberlin@gmail.com (Sam Berlin)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultElementVisitor -->
+  <!-- start class com.google.inject.spi.Dependency -->
+  <class name="Dependency" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="get" return="com.google.inject.spi.Dependency&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new dependency that is not attached to an injection point. The returned dependency is
+ nullable.]]>
+      </doc>
+    </method>
+    <method name="forInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectionPoints" type="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"/>
+      <doc>
+      <![CDATA[Returns the dependencies from the given injection points.]]>
+      </doc>
+    </method>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key to the binding that satisfies this dependency.]]>
+      </doc>
+    </method>
+    <method name="isNullable" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if null is a legal value for this dependency.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoint" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the injection point to which this dependency belongs, or null if this dependency isn't
+ attached to a particular injection point.]]>
+      </doc>
+    </method>
+    <method name="getParameterIndex" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the index of this dependency in the injection point's parameter list, or {@code -1} if
+ this dependency does not belong to a parameter list. Only method and constuctor dependencies
+ are elements in a parameter list.]]>
+      </doc>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[A variable that can be resolved by an injector.
+
+ <p>Use {@link #get} to build a freestanding dependency, or {@link InjectionPoint} to build one
+ that's attached to a constructor, method or field.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Dependency -->
+  <!-- start class com.google.inject.spi.DisableCircularProxiesOption -->
+  <class name="DisableCircularProxiesOption" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to disable circular proxies.
+
+ @author sameb@google.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DisableCircularProxiesOption -->
+  <!-- start interface com.google.inject.spi.Element -->
+  <interface name="Element"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns an arbitrary object containing information about the "place" where this element was
+ configured. Used by Guice in the production of descriptive error messages.
+
+ <p>Tools might specially handle types they know about; {@code StackTraceElement} is a good
+ example. Tools should simply call {@code toString()} on the source object if the type is
+ unfamiliar.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Accepts an element visitor. Invokes the visitor method specific to this element's type.
+
+ @param visitor to call back on]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Writes this module element to the given binder (optional operation).
+
+ @param binder to apply configuration element to
+ @throws UnsupportedOperationException if the {@code applyTo} method is not supported by this
+     element.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A core component of a module or injector.
+
+ <p>The elements of a module can be inspected, validated and rewritten. Use {@link
+ Elements#getElements(com.google.inject.Module[]) Elements.getElements()} to read the elements
+ from a module, and {@link Elements#getModule(Iterable) Elements.getModule()} to rewrite them.
+ This can be used for static analysis and generation of Guice modules.
+
+ <p>The elements of an injector can be inspected and exercised. Use {@link
+ com.google.inject.Injector#getBindings Injector.getBindings()} to reflect on Guice injectors.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.Element -->
+  <!-- start class com.google.inject.spi.Elements -->
+  <class name="Elements" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Elements"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getModule" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elements" type="java.lang.Iterable&lt;? extends com.google.inject.spi.Element&gt;"/>
+      <doc>
+      <![CDATA[Returns the module composed of {@code elements}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Exposes elements of a module so they can be inspected, validated or {@link
+ Element#applyTo(Binder) rewritten}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Elements -->
+  <!-- start interface com.google.inject.spi.ElementVisitor -->
+  <interface name="ElementVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a mapping from a key (type and optional annotation) to the strategy for getting
+ instances of the type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InterceptorBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of interceptors for matching methods of matching classes.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ScopeBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of a scope annotation with the scope that implements it.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeConverterBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of type converters for matching target types.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="request" type="com.google.inject.spi.InjectionRequest&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Visit a request to inject the instance fields and methods of an instance.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="request" type="com.google.inject.spi.StaticInjectionRequest"/>
+      <doc>
+      <![CDATA[Visit a request to inject the static fields and methods of type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a lookup of the provider for a type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a lookup of the members injector.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Visit an error message and the context in which it occured.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elements" type="com.google.inject.spi.PrivateElements"/>
+      <doc>
+      <![CDATA[Visit a collection of configuration elements for a {@linkplain com.google.inject.PrivateBinder
+ private binder}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeListenerBinding"/>
+      <doc>
+      <![CDATA[Visit an injectable type listener binding.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.RequireExplicitBindingsOption"/>
+      <doc>
+      <![CDATA[Visit a require explicit bindings command.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.DisableCircularProxiesOption"/>
+      <doc>
+      <![CDATA[Visit a disable circular proxies command.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visit elements.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ 
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ElementVisitor -->
+  <!-- start interface com.google.inject.spi.ExposedBinding -->
+  <interface name="ExposedBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getPrivateElements" return="com.google.inject.spi.PrivateElements"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the enclosed environment that holds the original binding.]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Unsupported. Always throws {@link UnsupportedOperationException}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a key exposed from an enclosed private environment.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ExposedBinding -->
+  <!-- start interface com.google.inject.spi.HasDependencies -->
+  <interface name="HasDependencies"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the known dependencies for this type. If this has dependencies whose values are not
+ known statically, a dependency for the {@link com.google.inject.Injector Injector} will be
+ included in the returned set.
+ 
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Implemented by {@link com.google.inject.Binding bindings}, {@link com.google.inject.Provider
+ providers} and instances that expose their dependencies explicitly.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.HasDependencies -->
+  <!-- start interface com.google.inject.spi.InjectionListener -->
+  <interface name="InjectionListener"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="afterInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectee" type="I"/>
+      <doc>
+      <![CDATA[Invoked by Guice after it injects the fields and methods of instance.
+
+ @param injectee instance that Guice injected dependencies into]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Listens for injections into instances of type {@code I}. Useful for performing further
+ injections, post-injection initialization, and more.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.InjectionListener -->
+  <!-- start class com.google.inject.spi.InjectionPoint -->
+  <class name="InjectionPoint" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="getMember" return="java.lang.reflect.Member"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the injected constructor, field, or method.]]>
+      </doc>
+    </method>
+    <method name="getDependencies" return="java.util.List&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the dependencies for this injection point. If the injection point is for a method or
+ constructor, the dependencies will correspond to that member's parameters. Field injection
+ points always have a single dependency for the field itself.
+
+ @return a possibly-empty list]]>
+      </doc>
+    </method>
+    <method name="isOptional" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if this injection point shall be skipped if the injector cannot resolve bindings
+ for all required dependencies. Both explicit bindings (as specified in a module), and implicit
+ bindings ({@literal @}{@link com.google.inject.ImplementedBy ImplementedBy}, default
+ constructors etc.) may be used to satisfy optional injection points.]]>
+      </doc>
+    </method>
+    <method name="isToolable" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if the element is annotated with {@literal @}{@link Toolable}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="getDeclaringType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the generic type that defines this injection point. If the member exists on a
+ parameterized type, the result will include more type information than the member's {@link
+ Member#getDeclaringClass() raw declaring class}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="forConstructor" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructor" type="java.lang.reflect.Constructor&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the specified constructor. If the declaring type of {@code
+ constructor} is parameterized (such as {@code List<T>}), prefer the overload that includes a
+ type literal.
+
+ @param constructor any single constructor present on {@code type}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="forConstructor" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructor" type="java.lang.reflect.Constructor&lt;T&gt;"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the specified constructor of {@code type}.
+
+ @param constructor any single constructor present on {@code type}.
+ @param type the concrete type that defines {@code constructor}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="forConstructorOf" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the injectable constructor of {@code type}.
+
+ @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
+     or a no-arguments constructor that is not private.
+ @throws ConfigurationException if there is no injectable constructor, more than one injectable
+     constructor, or if parameters of the injectable constructor are malformed, such as a
+     parameter with multiple binding annotations.]]>
+      </doc>
+    </method>
+    <method name="forConstructorOf" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the injectable constructor of {@code type}.
+
+ @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
+     or a no-arguments constructor that is not private.
+ @throws ConfigurationException if there is no injectable constructor, more than one injectable
+     constructor, or if parameters of the injectable constructor are malformed, such as a
+     parameter with multiple binding annotations.]]>
+      </doc>
+    </method>
+    <method name="forStaticMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all static method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forStaticMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all static method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forInstanceMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forInstanceMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A constructor, field or method that can receive injections. Typically this is a member with the
+ {@literal @}{@link Inject} annotation. For non-private, no argument constructors, the member may
+ omit the annotation.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InjectionPoint -->
+  <!-- start class com.google.inject.spi.InjectionRequest -->
+  <class name="InjectionRequest" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="InjectionRequest" type="java.lang.Object, com.google.inject.TypeLiteral&lt;T&gt;, T"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="ConfigurationException" type="com.google.inject.ConfigurationException"/>
+      <doc>
+      <![CDATA[Returns the instance methods and fields of {@code instance} that will be injected to fulfill
+ this request.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on the class of {@code
+      instance}, such as a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="R"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;R&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[A request to inject the instance fields and methods of an instance. Requests are created
+ explicitly in a module using {@link com.google.inject.Binder#requestInjection(Object)
+ requestInjection()} statements:
+ <pre>
+     requestInjection(serviceInstance);</pre>
+
+ @author mikeward@google.com (Mike Ward)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InjectionRequest -->
+  <!-- start interface com.google.inject.spi.InstanceBinding -->
+  <interface name="InstanceBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the user-supplied instance.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the field and method injection points of the instance, injected at injector-creation
+ time only.
+
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a single instance. The same instance is returned for every injection.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.InstanceBinding -->
+  <!-- start class com.google.inject.spi.InterceptorBinding -->
+  <class name="InterceptorBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassMatcher" return="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getMethodMatcher" return="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInterceptors" return="java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Registration of interceptors for matching methods of matching classes. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#bindInterceptor(
+ Matcher, Matcher, MethodInterceptor[]) bindInterceptor()} statements:
+ <pre>
+     bindInterceptor(Matchers.subclassesOf(MyAction.class),
+         Matchers.annotatedWith(Transactional.class),
+         new MyTransactionInterceptor());</pre>
+
+ or from an injectable type listener using {@link TypeEncounter#bindInterceptor(Matcher,
+ org.aopalliance.intercept.MethodInterceptor[]) TypeEncounter.bindInterceptor()}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InterceptorBinding -->
+  <!-- start interface com.google.inject.spi.LinkedKeyBinding -->
+  <interface name="LinkedKeyBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getLinkedKey" return="com.google.inject.Key&lt;? extends T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the linked key used to resolve injections. That binding can be retrieved from an
+ injector using {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a linked key. The other key's binding is used to resolve injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.LinkedKeyBinding -->
+  <!-- start class com.google.inject.spi.MembersInjectorLookup -->
+  <class name="MembersInjectorLookup" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="MembersInjectorLookup" type="java.lang.Object, com.google.inject.TypeLiteral&lt;T&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the type containing the members to be injected.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="initializeDelegate"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="delegate" type="com.google.inject.MembersInjector&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Sets the actual members injector.
+
+ @throws IllegalStateException if the delegate is already set]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="getDelegate" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the delegate members injector, or {@code null} if it has not yet been initialized.
+ The delegate will be initialized when this element is processed, or otherwise used to create
+ an injector.]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the looked up members injector. The result is not valid until this lookup has been
+ initialized, which usually happens when the injector is created. The members injector will
+ throw an {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A lookup of the members injector for a type. Lookups are created explicitly in a module using
+ {@link com.google.inject.Binder#getMembersInjector(Class) getMembersInjector()} statements:
+ <pre>
+     MembersInjector&lt;PaymentService&gt; membersInjector
+         = getMembersInjector(PaymentService.class);</pre>
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.MembersInjectorLookup -->
+  <!-- start class com.google.inject.spi.Message -->
+  <class name="Message" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.io.Serializable"/>
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="Message" type="java.util.List&lt;java.lang.Object&gt;, java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </constructor>
+    <constructor name="Message" type="java.lang.Object, java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="Message" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getSources" return="java.util.List&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the error message text.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <method name="getCause" return="java.lang.Throwable"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the throwable that caused this message, or {@code null} if this
+ message was not caused by a throwable.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An error message and the context in which it occured. Messages are usually created internally by
+ Guice and its extensions. Messages can be created explicitly in a module using {@link
+ com.google.inject.Binder#addError(Throwable) addError()} statements:
+ <pre>
+     try {
+       bindPropertiesFromFile();
+     } catch (IOException e) {
+       addError(e);
+     }</pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Message -->
+  <!-- start interface com.google.inject.spi.PrivateElements -->
+  <interface name="PrivateElements"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the configuration information in this private environment.]]>
+      </doc>
+    </method>
+    <method name="getInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the child injector that hosts these private elements, or null if the elements haven't
+ been used to create an injector.]]>
+      </doc>
+    </method>
+    <method name="getExposedKeys" return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the unique exposed keys for these private elements.]]>
+      </doc>
+    </method>
+    <method name="getExposedSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns an arbitrary object containing information about the "place" where this key was
+ exposed. Used by Guice in the production of descriptive error messages.
+
+ <p>Tools might specially handle types they know about; {@code StackTraceElement} is a good
+ example. Tools should simply call {@code toString()} on the source object if the type is
+ unfamiliar.
+
+ @param key one of the keys exposed by this module.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A private collection of elements that are hidden from the enclosing injector or module by
+ default. See {@link com.google.inject.PrivateModule PrivateModule} for details.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.PrivateElements -->
+  <!-- start interface com.google.inject.spi.ProviderBinding -->
+  <interface name="ProviderBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getProvidedKey" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key whose binding is used to {@link Provider#get provide instances}. That binding
+ can be retrieved from an injector using {@link com.google.inject.Injector#getBinding(Key)
+ Injector.getBinding(providedKey)}]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a {@link Provider} that delegates to the binding for the provided type. This binding
+ is used whenever a {@code Provider<T>} is injected (as opposed to injecting {@code T} directly).
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderBinding -->
+  <!-- start interface com.google.inject.spi.ProviderInstanceBinding -->
+  <interface name="ProviderInstanceBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getProviderInstance" return="com.google.inject.Provider&lt;? extends T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the user-supplied, unscoped provider.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the field and method injection points of the provider, injected at injector-creation
+ time only.
+
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a provider instance. The provider's {@code get} method is invoked to resolve
+ injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderInstanceBinding -->
+  <!-- start interface com.google.inject.spi.ProviderKeyBinding -->
+  <interface name="ProviderKeyBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getProviderKey" return="com.google.inject.Key&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key used to resolve the provider's binding. That binding can be retrieved from an
+ injector using {@link com.google.inject.Injector#getBinding(Key)
+ Injector.getBinding(providerKey)}]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a provider key. To resolve injections, the provider key is first resolved, then that
+ provider's {@code get} method is invoked.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderKeyBinding -->
+  <!-- start class com.google.inject.spi.ProviderLookup -->
+  <class name="ProviderLookup" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="ProviderLookup" type="java.lang.Object, com.google.inject.Key&lt;T&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="initializeDelegate"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="delegate" type="com.google.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Sets the actual provider.
+
+ @throws IllegalStateException if the delegate is already set]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="getDelegate" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the delegate provider, or {@code null} if it has not yet been initialized. The delegate
+ will be initialized when this element is processed, or otherwise used to create an injector.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the looked up provider. The result is not valid until this lookup has been initialized,
+ which usually happens when the injector is created. The provider will throw an {@code
+ IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A lookup of the provider for a type. Lookups are created explicitly in a module using
+ {@link com.google.inject.Binder#getProvider(Class) getProvider()} statements:
+ <pre>
+     Provider&lt;PaymentService&gt; paymentServiceProvider
+         = getProvider(PaymentService.class);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ProviderLookup -->
+  <!-- start interface com.google.inject.spi.ProviderWithDependencies -->
+  <interface name="ProviderWithDependencies"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Provider&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <doc>
+    <![CDATA[A provider with dependencies on other injected types. If a {@link Provider} has dependencies that
+ aren't specified in injections, this interface should be used to expose all dependencies.
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderWithDependencies -->
+  <!-- start interface com.google.inject.spi.ProviderWithExtensionVisitor -->
+  <interface name="ProviderWithExtensionVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Provider&lt;T&gt;"/>
+    <method name="acceptExtensionVisitor" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;B, V&gt;"/>
+      <param name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends B&gt;"/>
+      <doc>
+      <![CDATA[Instructs the extension determine if the visitor is an instance of a custom
+ extension visitor, and if so, visit it using that method. If the visitor is
+ not an instance of the custom extension visitor, this method <b>MUST</b>
+ call visitor.visit(binding).
+ <p> 
+ Due to issues with generics, the type parameters of this method do not
+ relate to the type of the provider. In practice, the 'B' type will always
+ be a supertype of 'T'.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A Provider that is part of an extension which supports a custom
+ BindingTargetVisitor.
+ <p> 
+ When an extension binds a provider instance, the provider can implement this
+ interface to allow users using the
+ {@link Binding#acceptTargetVisitor(BindingTargetVisitor)} method to visit a
+ custom visitor designed for that extension. A typical implementation within
+ the extension would look like
+ <pre> 
+ &lt;V, B> V acceptExtensionVisitor(BindingTargetVisitor&lt;B, V> visitor, ProviderInstanceBinding&lt;? extends B> binding) {
+   if(visitor instanceof MyCustomExtensionVisitor) {
+     return ((MyCustomExtensionVisitor&lt;B, V>)visitor).visitCustomExtension(customProperties, binding);
+   } else {
+     return visitor.visit(binding);
+   }
+ }</pre> 
+ 'MyCustomExtensionVisitor' in the example above would be an interface the
+ extension provides that users can implement in order to be notified of custom
+ extension information. These visitor interfaces must extend from
+ BindingTargetVisitor.
+
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderWithExtensionVisitor -->
+  <!-- start class com.google.inject.spi.RequireExplicitBindingsOption -->
+  <class name="RequireExplicitBindingsOption" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to require explicit bindings.
+
+ @author sameb@google.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.RequireExplicitBindingsOption -->
+  <!-- start class com.google.inject.spi.ScopeBinding -->
+  <class name="ScopeBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getAnnotationType" return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getScope" return="com.google.inject.Scope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Registration of a scope annotation with the scope that implements it. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#bindScope(Class, Scope) bindScope()}
+ statements:
+ <pre>
+     Scope recordScope = new RecordScope();
+     bindScope(RecordScoped.class, new RecordScope());</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ScopeBinding -->
+  <!-- start class com.google.inject.spi.StaticInjectionRequest -->
+  <class name="StaticInjectionRequest" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="java.lang.Class&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="ConfigurationException" type="com.google.inject.ConfigurationException"/>
+      <doc>
+      <![CDATA[Returns the static methods and fields of {@code type} that will be injected to fulfill this
+ request.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to inject the static fields and methods of a type. Requests are created
+ explicitly in a module using {@link com.google.inject.Binder#requestStaticInjection(Class[])
+ requestStaticInjection()} statements:
+ <pre>
+     requestStaticInjection(MyLegacyService.class);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.StaticInjectionRequest -->
+  <!-- start class com.google.inject.spi.Toolable -->
+  <class name="Toolable"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Instructs an {@link Injector} running in {@link Stage#TOOL} that a method should be injected.
+ This is typically useful for for extensions to Guice that perform additional validation in an
+ injected method or field.  This only applies to objects that are already constructed when
+ bindings are created (ie., something bound using {@link
+ com.google.inject.binder.LinkedBindingBuilder#toProvider toProvider}, {@link
+ com.google.inject.binder.LinkedBindingBuilder#toInstance toInstance}, or {@link
+ com.google.inject.Binder#requestInjection requestInjection}.
+ 
+ @author sberlin@gmail.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Toolable -->
+  <!-- start interface com.google.inject.spi.TypeConverter -->
+  <interface name="TypeConverter"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="convert" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.String"/>
+      <param name="toType" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Converts a string value. Throws an exception if a conversion error occurs.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Converts constant string values to a different type.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeConverter -->
+  <!-- start class com.google.inject.spi.TypeConverterBinding -->
+  <class name="TypeConverterBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="TypeConverterBinding" type="java.lang.Object, com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;, com.google.inject.spi.TypeConverter"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTypeMatcher" return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTypeConverter" return="com.google.inject.spi.TypeConverter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Registration of type converters for matching target types. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#convertToTypes(Matcher,
+ TypeConverter) convertToTypes()} statements:
+ <pre>
+     convertToTypes(Matchers.only(TypeLiteral.get(DateTime.class)), new DateTimeConverter());</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.TypeConverterBinding -->
+  <!-- start interface com.google.inject.spi.TypeEncounter -->
+  <interface name="TypeEncounter"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[Records an error message for type {@code I} which will be presented to the user at a later
+ time. Unlike throwing an exception, this enable us to continue configuring the Injector and
+ discover more errors. Uses {@link String#format(String, Object[])} to insert the arguments
+ into the message.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[Records an exception for type {@code I}, the full details of which will be logged, and the
+ message of which will be presented to the user at a later time. If your type listener calls
+ something that you worry may fail, you should catch the exception and pass it to this method.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Records an error message to be presented to the user at a later time.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key. The returned
+ provider will not be valid until the injector has been created. The provider will throw an
+ {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection type. The returned
+ provider will not be valid until the injetor has been created. The provider will throw an
+ {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ injector has been created. The members injector will throw an {@code IllegalStateException}
+ if you try to use it beforehand.
+
+ @param typeLiteral type to get members injector for]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ injector has been created. The members injector will throw an {@code IllegalStateException}
+ if you try to use it beforehand.
+
+ @param type type to get members injector for]]>
+      </doc>
+    </method>
+    <method name="register"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="membersInjector" type="com.google.inject.MembersInjector&lt;? super I&gt;"/>
+      <doc>
+      <![CDATA[Registers a members injector for type {@code I}. Guice will use the members injector after its
+ performed its own injections on an instance of {@code I}.]]>
+      </doc>
+    </method>
+    <method name="register"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="listener" type="com.google.inject.spi.InjectionListener&lt;? super I&gt;"/>
+      <doc>
+      <![CDATA[Registers an injection listener for type {@code I}. Guice will notify the listener after all
+ injections have been performed on an instance of {@code I}.]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[Binds method interceptor[s] to methods matched in type {@code I} and its supertypes. A
+ method is eligible for interception if:
+
+ <ul>
+  <li>Guice created the instance the method is on</li>
+  <li>Neither the enclosing type nor the method is final</li>
+  <li>And the method is package-private or more accessible</li>
+ </ul>
+
+ @param methodMatcher matches methods the interceptor should apply to. For
+     example: {@code annotatedWith(Transactional.class)}.
+ @param interceptors to bind]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Context of an injectable type encounter. Enables reporting errors, registering injection
+ listeners and binding method interceptors for injectable type {@code I}. It is an error to use
+ an encounter after the {@link TypeListener#hear(TypeLiteral, TypeEncounter) hear()} method has
+ returned.
+
+ @param <I> the injectable type encountered
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeEncounter -->
+  <!-- start interface com.google.inject.spi.TypeListener -->
+  <interface name="TypeListener"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="hear"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;I&gt;"/>
+      <param name="encounter" type="com.google.inject.spi.TypeEncounter&lt;I&gt;"/>
+      <doc>
+      <![CDATA[Invoked when Guice encounters a new type eligible for constructor or members injection.
+ Called during injector creation (or afterwords if Guice encounters a type at run time and
+ creates a JIT binding).
+
+ @param type encountered by Guice
+ @param encounter context of this encounter, enables reporting errors, registering injection
+     listeners and binding method interceptors for {@code type}.
+
+ @param <I> the injectable type]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Listens for Guice to encounter injectable types. If a given type has its constructor injected in
+ one situation but only its methods and fields injected in another, Guice will notify this
+ listener once.
+
+ <p>Useful for extra type checking, {@linkplain TypeEncounter#register(InjectionListener)
+ registering injection listeners}, and {@linkplain TypeEncounter#bindInterceptor(
+ com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])
+ binding method interceptors}.
+ 
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeListener -->
+  <!-- start class com.google.inject.spi.TypeListenerBinding -->
+  <class name="TypeListenerBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getListener" return="com.google.inject.spi.TypeListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the registered listener.]]>
+      </doc>
+    </method>
+    <method name="getTypeMatcher" return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the type matcher which chooses which types the listener should be notified of.]]>
+      </doc>
+    </method>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Binds types (picked using a Matcher) to an type listener. Registrations are created explicitly in
+ a module using {@link com.google.inject.Binder#bindListener(Matcher, TypeListener)} statements:
+
+ <pre>
+     register(only(new TypeLiteral&lt;PaymentService&lt;CreditCard>>() {}), listener);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.TypeListenerBinding -->
+  <!-- start interface com.google.inject.spi.UntargettedBinding -->
+  <interface name="UntargettedBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <doc>
+    <![CDATA[An untargetted binding. This binding indicates that the injector should use its implicit binding
+ strategies to resolve injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.UntargettedBinding -->
+</package>
+<package name="com.google.inject.spring">
+  <!-- start class com.google.inject.spring.SpringIntegration -->
+  <class name="SpringIntegration" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="fromSpring" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a provider which looks up objects from Spring using the given name.
+ Expects a binding to {@link
+ org.springframework.beans.factory.BeanFactory}. Example usage:
+
+ <pre>
+ bind(DataSource.class)
+   .toProvider(fromSpring(DataSource.class, "dataSource"));
+ </pre>]]>
+      </doc>
+    </method>
+    <method name="bindAll"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="beanFactory" type="ListableBeanFactory"/>
+      <doc>
+      <![CDATA[Binds all Spring beans from the given factory by name. For a Spring bean
+ named "foo", this method creates a binding to the bean's type and
+ {@code @Named("foo")}.
+
+ @see com.google.inject.name.Named
+ @see com.google.inject.name.Names#named(String)]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Integrates Guice with Spring.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spring.SpringIntegration -->
+</package>
+<package name="com.google.inject.struts2">
+  <!-- start class com.google.inject.struts2.GuiceObjectFactory -->
+  <class name="GuiceObjectFactory" extends="ObjectFactory"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="Use {@link com.google.inject.servlet.Struts2Factory} instead.">
+    <constructor name="GuiceObjectFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="isNoArgConstructorRequired" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassInstance" return="java.lang.Class"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException"/>
+    </method>
+    <method name="buildBean" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class"/>
+      <param name="extraContext" type="java.util.Map"/>
+    </method>
+    <method name="buildInterceptor" return="Interceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorConfig" type="InterceptorConfig"/>
+      <param name="interceptorRefParams" type="java.util.Map"/>
+      <exception name="ConfigurationException" type="ConfigurationException"/>
+    </method>
+    <doc>
+    <![CDATA[@deprecated Use {@link com.google.inject.servlet.Struts2Factory} instead.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.struts2.GuiceObjectFactory -->
+  <!-- start class com.google.inject.struts2.Struts2Factory -->
+  <class name="Struts2Factory" extends="ObjectFactory"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Struts2Factory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="isNoArgConstructorRequired" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassInstance" return="java.lang.Class&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException"/>
+    </method>
+    <method name="buildBean" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class"/>
+      <param name="extraContext" type="java.util.Map&lt;java.lang.String, java.lang.Object&gt;"/>
+    </method>
+    <method name="buildInterceptor" return="Interceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorConfig" type="InterceptorConfig"/>
+      <param name="interceptorRefParams" type="java.util.Map"/>
+      <exception name="ConfigurationException" type="ConfigurationException"/>
+    </method>
+    <doc>
+    <![CDATA[Cleanup up version from Bob's GuiceObjectFactory. Now works properly with
+ GS2 and fixes several bugs.
+
+ @author dhanji@gmail.com
+ @author benmccann.com]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.struts2.Struts2Factory -->
+  <!-- start class com.google.inject.struts2.Struts2GuicePluginModule -->
+  <class name="Struts2GuicePluginModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Struts2GuicePluginModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Initializes the Struts 2 Guice Plugin.
+ Must be added to the injector returned by
+     {@link GuiceServletContextListener.getInjector()}.
+
+ @author benmccann.com]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.struts2.Struts2GuicePluginModule -->
+</package>
+<package name="com.google.inject.throwingproviders">
+  <!-- start interface com.google.inject.throwingproviders.CheckedProvider -->
+  <interface name="CheckedProvider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="get" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="Exception" type="java.lang.Exception"/>
+    </method>
+    <doc>
+    <![CDATA[Alternative to the Guice {@link com.google.inject.Provider} that throws
+ a checked Exception. Users may not inject {@code T} directly.
+
+ <p>This interface must be extended to use application-specific exception types.
+ Such subinterfaces may not define new methods, but may narrow the exception type.
+ <pre>
+ public interface RemoteProvider&lt;T&gt; extends CheckedProvider&lt;T&gt; { 
+   T get() throws CustomExceptionOne, CustomExceptionTwo;
+ }
+ </pre>
+
+ <p>When this type is bound using {@link ThrowingProviderBinder}, the value returned
+ or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get}
+ will invoked at most once within each scope.
+ 
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.throwingproviders.CheckedProvider -->
+  <!-- start class com.google.inject.throwingproviders.CheckedProvides -->
+  <class name="CheckedProvides"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates methods of a {@link Module} to create a {@link CheckedProvider}
+ method binding that can throw exceptions. The method's return type is bound
+ to a {@link CheckedProvider} that can be injected. Guice will pass
+ dependencies to the method as parameters. Install {@literal @}CheckedProvides
+ methods by using
+ {@link ThrowingProviderBinder#forModule(com.google.inject.Module)} on the
+ module where the methods are declared.
+ 
+ @author sameb@google.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.CheckedProvides -->
+  <!-- start interface com.google.inject.throwingproviders.ThrowingProvider -->
+  <interface name="ThrowingProvider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="use {@link CheckedProvider} instead.">
+    <implements name="com.google.inject.throwingproviders.CheckedProvider&lt;T&gt;"/>
+    <method name="get" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="Exception" type="java.lang.Exception"/>
+    </method>
+    <doc>
+    <![CDATA[Alternative to the Guice {@link com.google.inject.Provider} that throws
+ a checked Exception. Users may not inject {@code T} directly.
+
+ <p>This interface must be extended to use application-specific exception types.
+ Such subinterfaces may not define new methods:
+ <pre>
+ public interface RemoteProvider&lt;T&gt; extends ThrowingProvider&lt;T, RemoteException&gt; { }
+ </pre>
+
+ <p>When this type is bound using {@link ThrowingProviderBinder}, the value returned
+ or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get}
+ will invoked at most once within each scope.
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)
+ @deprecated use {@link CheckedProvider} instead.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.throwingproviders.ThrowingProvider -->
+  <!-- start class com.google.inject.throwingproviders.ThrowingProviderBinder -->
+  <class name="ThrowingProviderBinder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="create" return="com.google.inject.throwingproviders.ThrowingProviderBinder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="forModule" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[Returns a module that installs {@literal @}{@link CheckedProvides} methods.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interfaceType" type="java.lang.Class&lt;P&gt;"/>
+      <param name="valueType" type="java.lang.reflect.Type"/>
+    </method>
+    <doc>
+    <![CDATA[<p>Builds a binding for a {@link CheckedProvider}.
+ 
+ <p>You can use a fluent API and custom providers:
+ <pre><code>ThrowingProviderBinder.create(binder())
+    .bind(RemoteProvider.class, Customer.class)
+    .to(RemoteCustomerProvider.class)
+    .in(RequestScope.class);
+ </code></pre>
+ or, you can use throwing provider methods:
+ <pre><code>class MyModule extends AbstractModule {
+   configure() {
+     ThrowingProviderBinder.install(this, binder());
+   }
+   
+   {@literal @}CheckedProvides(RemoteProvider.class)
+   {@literal @}RequestScope
+   Customer provideCustomer(FlakyCustomerCreator creator) throws RemoteException {
+     return creator.getCustomerOrThrow();
+   }
+ }
+ </code></pre>
+ 
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.ThrowingProviderBinder -->
+  <!-- start class com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder -->
+  <class name="ThrowingProviderBinder.SecondaryBinder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ThrowingProviderBinder.SecondaryBinder" type="java.lang.Class&lt;P&gt;, java.lang.reflect.Type"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="annotatedWith" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="target" type="P extends com.google.inject.throwingproviders.CheckedProvider"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetType" type="java.lang.Class&lt;? extends P&gt;"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetKey" type="com.google.inject.Key&lt;? extends P&gt;"/>
+    </method>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder -->
+</package>
+<package name="com.google.inject.tools.jmx">
+  <!-- start interface com.google.inject.tools.jmx.ManagedBindingMBean -->
+  <interface name="ManagedBindingMBean"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSource" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the source of this binding.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the provider to which this binding is bound.]]>
+      </doc>
+    </method>
+    <method name="getKey" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the binding key.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[JMX interface to bindings.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.tools.jmx.ManagedBindingMBean -->
+  <!-- start class com.google.inject.tools.jmx.Manager -->
+  <class name="Manager" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Manager"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="manage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="domain" type="java.lang.String"/>
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Registers all the bindings of an Injector with the platform MBean server.
+ Consider using the name of your root {@link Module} class as the domain.]]>
+      </doc>
+    </method>
+    <method name="manage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="server" type="javax.management.MBeanServer"/>
+      <param name="domain" type="java.lang.String"/>
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Registers all the bindings of an Injector with the given MBean server.
+ Consider using the name of your root {@link Module} class as the domain.]]>
+      </doc>
+    </method>
+    <method name="main"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="args" type="java.lang.String[]"/>
+      <exception name="Exception" type="java.lang.Exception"/>
+      <doc>
+      <![CDATA[Run with no arguments for usage instructions.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Provides a JMX interface to Guice.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.tools.jmx.Manager -->
+</package>
+<package name="com.google.inject.util">
+  <!-- start class com.google.inject.util.Modules -->
+  <class name="Modules" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="override" return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a builder that creates a module that overlays override modules over the given
+ modules. If a key is bound in both sets of modules, only the binding from the override modules
+ is kept. If a single {@link PrivateModule} is supplied or all elements are from
+ a single {@link PrivateBinder}, then this will overwrite the private bindings.
+ Otherwise, private bindings will not be overwritten unless they are exposed. 
+ This can be used to replace the bindings of a production module with test bindings:
+ <pre>
+ Module functionalTestModule
+     = Modules.override(new ProductionModule()).with(new TestModule());
+ </pre>
+
+ <p>Prefer to write smaller modules that can be reused and tested without overrides.
+
+ @param modules the modules whose bindings are open to be overridden]]>
+      </doc>
+    </method>
+    <method name="override" return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a builder that creates a module that overlays override modules over the given
+ modules. If a key is bound in both sets of modules, only the binding from the override modules
+ is kept. If a single {@link PrivateModule} is supplied or all elements are from
+ a single {@link PrivateBinder}, then this will overwrite the private bindings.
+ Otherwise, private bindings will not be overwritten unless they are exposed. 
+ This can be used to replace the bindings of a production module with test bindings:
+ <pre>
+ Module functionalTestModule
+     = Modules.override(getProductionModules()).with(getTestModules());
+ </pre>
+
+ <p>Prefer to write smaller modules that can be reused and tested without overrides.
+
+ @param modules the modules whose bindings are open to be overridden]]>
+      </doc>
+    </method>
+    <method name="combine" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a new module that installs all of {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="combine" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a new module that installs all of {@code modules}.]]>
+      </doc>
+    </method>
+    <field name="EMPTY_MODULE" type="com.google.inject.Module"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+    </field>
+    <doc>
+    <![CDATA[Static utility methods for creating and working with instances of {@link Module}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Modules -->
+  <!-- start interface com.google.inject.util.Modules.OverriddenModuleBuilder -->
+  <interface name="Modules.OverriddenModuleBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="with" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="overrides" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+      </doc>
+    </method>
+    <method name="with" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="overrides" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.util.Modules.OverriddenModuleBuilder -->
+  <!-- start class com.google.inject.util.Providers -->
+  <class name="Providers" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="of" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Returns a provider which always provides {@code instance}.  This should not
+ be necessary to use in your application, but is helpful for several types
+ of unit tests.
+
+ @param instance the instance that should always be provided.  This is also
+     permitted to be null, to enable aggressive testing, although in real
+     life a Guice-supplied Provider will never return null.]]>
+      </doc>
+    </method>
+    <method name="guicify" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="provider" type="javax.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a Guice-friendly {@code com.google.inject.Provider} for the given
+ JSR-330 {@code javax.inject.Provider}. The converse method is unnecessary,
+ since Guice providers directly implement the JSR-330 interface.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Static utility methods for creating and working with instances of
+ {@link Provider}.
+
+ @author Kevin Bourrillion (kevinb9n@gmail.com)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Providers -->
+  <!-- start class com.google.inject.util.Types -->
+  <class name="Types" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="newParameterizedType" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="rawType" type="java.lang.reflect.Type"/>
+      <param name="typeArguments" type="java.lang.reflect.Type[]"/>
+      <doc>
+      <![CDATA[Returns a new parameterized type, applying {@code typeArguments} to
+ {@code rawType}. The returned type does not have an owner type.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="newParameterizedTypeWithOwner" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="ownerType" type="java.lang.reflect.Type"/>
+      <param name="rawType" type="java.lang.reflect.Type"/>
+      <param name="typeArguments" type="java.lang.reflect.Type[]"/>
+      <doc>
+      <![CDATA[Returns a new parameterized type, applying {@code typeArguments} to
+ {@code rawType} and enclosed by {@code ownerType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="arrayOf" return="java.lang.reflect.GenericArrayType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="componentType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns an array type whose elements are all instances of
+ {@code componentType}.
+
+ @return a {@link java.io.Serializable serializable} generic array type.]]>
+      </doc>
+    </method>
+    <method name="subtypeOf" return="java.lang.reflect.WildcardType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bound" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type that represents an unknown type that extends {@code bound}.
+ For example, if {@code bound} is {@code CharSequence.class}, this returns
+ {@code ? extends CharSequence}. If {@code bound} is {@code Object.class},
+ this returns {@code ?}, which is shorthand for {@code ? extends Object}.]]>
+      </doc>
+    </method>
+    <method name="supertypeOf" return="java.lang.reflect.WildcardType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bound" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type that represents an unknown supertype of {@code bound}. For
+ example, if {@code bound} is {@code String.class}, this returns {@code ?
+ super String}.]]>
+      </doc>
+    </method>
+    <method name="listOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elementType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link List} whose elements are of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="setOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elementType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Set} whose elements are of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="mapOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="keyType" type="java.lang.reflect.Type"/>
+      <param name="valueType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Map} whose keys are of type
+ {@code keyType} and whose values are of type {@code valueType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="providerOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providedType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Provider} that provides elements of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Static methods for working with types.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Types -->
+</package>
+
+</api>
diff --git a/latest-api-diffs/4.0.xml b/latest-api-diffs/4.0.xml
new file mode 100644
index 0000000..1b1e7d2
--- /dev/null
+++ b/latest-api-diffs/4.0.xml
@@ -0,0 +1,10774 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<!-- on Thu Mar 20 20:36:47 PDT 2014 -->
+
+<api
+  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+  xsi:noNamespaceSchemaLocation='api.xsd'
+  name="4.0"
+  jdversion="1.1.1">
+
+<!--  Command line arguments =  -doclet jdiff.JDiff -docletpath /Users/cgruber/OpenSource/guice/googlecode-master/lib/build/jdiff/jdiff.jar:/Users/cgruber/OpenSource/guice/googlecode-master/lib/build/jdiff/xerces.jar -classpath /Users/cgruber/OpenSource/guice/googlecode-master/lib/javax.inject.jar:/Users/cgruber/OpenSource/guice/googlecode-master/lib/aopalliance.jar:/Users/cgruber/OpenSource/guice/googlecode-master/lib/guava-16.0.1.jar -doclet jdiff.JDiff -docletpath /Users/cgruber/OpenSource/guice/googlecode-master/lib/build/jdiff/jdiff.jar:/Users/cgruber/OpenSource/guice/googlecode-master/lib/build/jdiff/xerces.jar -apidir build/docs/latest-api-diffs -apiname 4.0 -->
+<package name="com.google.inject">
+  <!-- start class com.google.inject.AbstractModule -->
+  <class name="AbstractModule" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Module"/>
+    <constructor name="AbstractModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="true"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="builder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="configure"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Configures a {@link Binder} via the exposed methods.]]>
+      </doc>
+    </method>
+    <method name="binder" return="com.google.inject.Binder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets direct access to the underlying {@code Binder}.]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[@see Binder#bindScope(Class, Scope)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Key)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Class)]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#bindConstant()]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[@see Binder#install(Module)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[@see Binder#addError(String, Object[])]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Throwable)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Message)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[@see Binder#requestInjection(Object)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[@see Binder#requestStaticInjection(Class[])]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindInterceptor(com.google.inject.matcher.Matcher,
+  com.google.inject.matcher.Matcher,
+  org.aopalliance.intercept.MethodInterceptor[])]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Adds a dependency from this module to {@code key}. When the injector is
+ created, Guice will report an error if {@code key} cannot be injected.
+ Note that this requirement may be satisfied by implicit binding, such as
+ a public no-arguments constructor.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Adds a dependency from this module to {@code type}. When the injector is
+ created, Guice will report an error if {@code type} cannot be injected.
+ Note that this requirement may be satisfied by implicit binding, such as
+ a public no-arguments constructor.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Key)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Class)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[@see Binder#convertToTypes
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#currentStage() 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(Class)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(TypeLiteral)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[@see Binder#bindListener(com.google.inject.matcher.Matcher,
+  com.google.inject.spi.TypeListener)
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="bindingMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.Binding&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.ProvisionListener[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindListener(Matcher, ProvisionListener...)
+ @since 4.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A support class for {@link Module}s which reduces repetition and results in
+ a more readable configuration. Simply extend this class, implement {@link
+ #configure()}, and call the inherited methods which mirror those found in
+ {@link Binder}. For example:
+
+ <pre>
+ public class MyModule extends AbstractModule {
+   protected void configure() {
+     bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
+     bind(CreditCardPaymentService.class);
+     bind(PaymentService.class).to(CreditCardPaymentService.class);
+     bindConstant().annotatedWith(Names.named("port")).to(8080);
+   }
+ }
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.AbstractModule -->
+  <!-- start interface com.google.inject.Binder -->
+  <interface name="Binder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="bindInterceptor"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[Binds method interceptor[s] to methods matched by class and method matchers. A method is
+ eligible for interception if:
+
+ <ul>
+  <li>Guice created the instance the method is on</li>
+  <li>Neither the enclosing type nor the method is final</li>
+  <li>And the method is package-private, protected, or public</li>
+ </ul>
+
+ @param classMatcher matches classes the interceptor should apply to. For
+     example: {@code only(Runnable.class)}.
+ @param methodMatcher matches methods the interceptor should apply to. For
+     example: {@code annotatedWith(Transactional.class)}.
+ @param interceptors to bind.  The interceptors are called in the order they
+     are given.]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[Binds a scope to an annotation.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[See the EDSL examples at {@link Binder}.]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject instance fields
+ and methods of the given object.
+
+ @param type of instance
+ @param instance for which members will be injected
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject instance fields
+ and methods of the given object.
+
+ @param instance for which members will be injected
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[Upon successful creation, the {@link Injector} will inject static fields
+ and methods in the given classes.
+
+ @param types for which static members will be injected]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[Uses the given module to configure more bindings.]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the current stage.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[Records an error message which will be presented to the user at a later
+ time. Unlike throwing an exception, this enable us to continue
+ configuring the Injector and discover more errors. Uses {@link
+ String#format(String, Object[])} to insert the arguments into the
+ message.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[Records an exception, the full details of which will be logged, and the
+ message of which will be presented to the user at a later
+ time. If your Module calls something that you worry may fail, you should
+ catch the exception and pass it into this.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Records an error message to be presented to the user at a later time.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key.
+ The returned provider will not be valid until the {@link Injector} has been
+ created. The provider will throw an {@code IllegalStateException} if you
+ try to use it beforehand.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection type.
+ The returned provider will not be valid until the {@link Injector} has been
+ created. The provider will throw an {@code IllegalStateException} if you
+ try to use it beforehand.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ {@link Injector} has been created. The members injector will throw an {@code
+ IllegalStateException} if you try to use it beforehand.
+
+ @param typeLiteral type to get members injector for
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ {@link Injector} has been created. The members injector will throw an {@code
+ IllegalStateException} if you try to use it beforehand.
+
+ @param type type to get members injector for
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[Binds a type converter. The injector will use the given converter to
+ convert string constants to matching types as needed.
+
+ @param typeMatcher matches types the converter can handle
+ @param converter converts values
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[Registers a listener for injectable types. Guice will notify the listener when it encounters
+ injectable types matched by the given type matcher.
+
+ @param typeMatcher that matches injectable types the listener should be notified of
+ @param listener for injectable types matched by typeMatcher
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bindingMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.Binding&lt;?&gt;&gt;"/>
+      <param name="listeners" type="com.google.inject.spi.ProvisionListener[]"/>
+      <doc>
+      <![CDATA[Registers listeners for provisioned objects. Guice will notify the
+ listeners just before and after the object is provisioned. Provisioned
+ objects that are also injectable (everything except objects provided
+ through Providers) can also be notified through TypeListeners registered in
+ {@link #bindListener}.
+ 
+ @param bindingMatcher that matches bindings of provisioned objects the listener
+          should be notified of
+ @param listeners for provisioned objects matched by bindingMatcher 
+ @since 4.0]]>
+      </doc>
+    </method>
+    <method name="withSource" return="com.google.inject.Binder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a binder that uses {@code source} as the reference location for
+ configuration errors. This is typically a {@link StackTraceElement}
+ for {@code .java} source but it could any binding source, such as the
+ path to a {@code .properties} file.
+
+ @param source any object representing the source location and has a
+     concise {@link Object#toString() toString()} value
+ @return a binder that shares its configuration with this binder
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="skipSources" return="com.google.inject.Binder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classesToSkip" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[Returns a binder that skips {@code classesToSkip} when identify the
+ calling code. The caller's {@link StackTraceElement} is used to locate
+ the source of configuration errors.
+
+ @param classesToSkip library classes that create bindings on behalf of
+      their clients.
+ @return a binder that shares its configuration with this binder.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="newPrivateBinder" return="com.google.inject.PrivateBinder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a new private child environment for bindings and other configuration. The returned
+ binder can be used to add and configuration information in this environment. See {@link
+ PrivateModule} for details.
+
+ @return a binder that inherits configuration from this binder. Only exposed configuration on
+      the returned binder will be visible to this binder.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="requireExplicitBindings"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Instructs the Injector that bindings must be listed in a Module in order to
+ be injected. Classes that are not explicitly bound in a module cannot be
+ injected. Bindings created through a linked binding (
+ <code>bind(Foo.class).to(FooImpl.class)</code>) are allowed, but the
+ implicit binding (<code>FooImpl</code>) cannot be directly injected unless
+ it is also explicitly bound (<code>bind(FooImpl.class)</code>).
+ <p>
+ Tools can still retrieve bindings for implicit bindings (bindings created
+ through a linked binding) if explicit bindings are required, however
+ {@link Binding#getProvider} will fail.
+ <p>
+ By default, explicit bindings are not required.
+ <p>
+ If a parent injector requires explicit bindings, then all child injectors
+ (and private modules within that injector) also require explicit bindings.
+ If a parent does not require explicit bindings, a child injector or private
+ module may optionally declare itself as requiring explicit bindings. If it
+ does, the behavior is limited only to that child or any grandchildren. No
+ siblings of the child will require explicit bindings.
+ <p>
+ If the parent did not require explicit bindings but the child does, it is
+ possible that a linked binding in the child may add a JIT binding to the
+ parent. The child will not be allowed to reference the target binding
+ directly, but the parent and other children of the parent may be able to.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="disableCircularProxies"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Prevents Guice from constructing a {@link Proxy} when a circular dependency
+ is found.  By default, circular proxies are not disabled.
+ <p>
+ If a parent injector disables circular proxies, then all child injectors
+ (and private modules within that injector) also disable circular proxies.
+ If a parent does not disable circular proxies, a child injector or private
+ module may optionally declare itself as disabling circular proxies. If it
+ does, the behavior is limited only to that child or any grandchildren. No
+ siblings of the child will disable circular proxies.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="requireAtInjectOnConstructors"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Requires that a {@literal @}{@link Inject} annotation exists on a constructor in order for
+ Guice to consider it an eligible injectable class. By default, Guice will inject classes that
+ have a no-args constructor if no {@literal @}{@link Inject} annotation exists on any
+ constructor.
+ <p>
+ If the class is bound using {@link LinkedBindingBuilder#toConstructor}, Guice will still inject
+ that constructor regardless of annotations.
+
+ @since 4.0]]>
+      </doc>
+    </method>
+    <method name="requireExactBindingAnnotations"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Requires that Guice finds an exactly matching binding annotation.  This disables the
+ error-prone feature in Guice where it can substitute a binding for
+ <code>{@literal @}Named Foo</code> when attempting to inject
+ <code>{@literal @}Named("foo") Foo</code>.
+
+ @since 4.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Collects configuration information (primarily <i>bindings</i>) which will be
+ used to create an {@link Injector}. Guice provides this object to your
+ application's {@link Module} implementors so they may each contribute
+ their own bindings and other registrations.
+
+ <h3>The Guice Binding EDSL</h3>
+
+ Guice uses an <i>embedded domain-specific language</i>, or EDSL, to help you
+ create bindings simply and readably.  This approach is great for overall
+ usability, but it does come with a small cost: <b>it is difficult to
+ learn how to use the Binding EDSL by reading
+ method-level javadocs</b>.  Instead, you should consult the series of
+ examples below.  To save space, these examples omit the opening
+ {@code binder}, just as you will if your module extends
+ {@link AbstractModule}.
+
+ <pre>
+     bind(ServiceImpl.class);</pre>
+
+ This statement does essentially nothing; it "binds the {@code ServiceImpl}
+ class to itself" and does not change Guice's default behavior.  You may still
+ want to use this if you prefer your {@link Module} class to serve as an
+ explicit <i>manifest</i> for the services it provides.  Also, in rare cases,
+ Guice may be unable to validate a binding at injector creation time unless it
+ is given explicitly.
+
+ <pre>
+     bind(Service.class).to(ServiceImpl.class);</pre>
+
+ Specifies that a request for a {@code Service} instance with no binding
+ annotations should be treated as if it were a request for a
+ {@code ServiceImpl} instance. This <i>overrides</i> the function of any
+ {@link ImplementedBy @ImplementedBy} or {@link ProvidedBy @ProvidedBy}
+ annotations found on {@code Service}, since Guice will have already
+ "moved on" to {@code ServiceImpl} before it reaches the point when it starts
+ looking for these annotations.
+
+ <pre>
+     bind(Service.class).toProvider(ServiceProvider.class);</pre>
+
+ In this example, {@code ServiceProvider} must extend or implement
+ {@code Provider<Service>}. This binding specifies that Guice should resolve
+ an unannotated injection request for {@code Service} by first resolving an
+ instance of {@code ServiceProvider} in the regular way, then calling
+ {@link Provider#get get()} on the resulting Provider instance to obtain the
+ {@code Service} instance.
+
+ <p>The {@link Provider} you use here does not have to be a "factory"; that
+ is, a provider which always <i>creates</i> each instance it provides.
+ However, this is generally a good practice to follow.  You can then use
+ Guice's concept of {@link Scope scopes} to guide when creation should happen
+ -- "letting Guice work for you".
+
+ <pre>
+     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);</pre>
+
+ Like the previous example, but only applies to injection requests that use
+ the binding annotation {@code @Red}.  If your module also includes bindings
+ for particular <i>values</i> of the {@code @Red} annotation (see below),
+ then this binding will serve as a "catch-all" for any values of {@code @Red}
+ that have no exact match in the bindings.
+ 
+ <pre>
+     bind(ServiceImpl.class).in(Singleton.class);
+     // or, alternatively
+     bind(ServiceImpl.class).in(Scopes.SINGLETON);</pre>
+
+ Either of these statements places the {@code ServiceImpl} class into
+ singleton scope.  Guice will create only one instance of {@code ServiceImpl}
+ and will reuse it for all injection requests of this type.  Note that it is
+ still possible to bind another instance of {@code ServiceImpl} if the second
+ binding is qualified by an annotation as in the previous example.  Guice is
+ not overly concerned with <i>preventing</i> you from creating multiple
+ instances of your "singletons", only with <i>enabling</i> your application to
+ share only one instance if that's all you tell Guice you need.
+
+ <p><b>Note:</b> a scope specified in this way <i>overrides</i> any scope that
+ was specified with an annotation on the {@code ServiceImpl} class.
+ 
+ <p>Besides {@link Singleton}/{@link Scopes#SINGLETON}, there are
+ servlet-specific scopes available in
+ {@code com.google.inject.servlet.ServletScopes}, and your Modules can
+ contribute their own custom scopes for use here as well.
+
+ <pre>
+     bind(new TypeLiteral&lt;PaymentService&lt;CreditCard>>() {})
+         .to(CreditCardPaymentService.class);</pre>
+
+ This admittedly odd construct is the way to bind a parameterized type. It
+ tells Guice how to honor an injection request for an element of type
+ {@code PaymentService<CreditCard>}. The class
+ {@code CreditCardPaymentService} must implement the
+ {@code PaymentService<CreditCard>} interface.  Guice cannot currently bind or
+ inject a generic type, such as {@code Set<E>}; all type parameters must be
+ fully specified.
+
+ <pre>
+     bind(Service.class).toInstance(new ServiceImpl());
+     // or, alternatively
+     bind(Service.class).toInstance(SomeLegacyRegistry.getService());</pre>
+
+ In this example, your module itself, <i>not Guice</i>, takes responsibility
+ for obtaining a {@code ServiceImpl} instance, then asks Guice to always use
+ this single instance to fulfill all {@code Service} injection requests.  When
+ the {@link Injector} is created, it will automatically perform field
+ and method injection for this instance, but any injectable constructor on
+ {@code ServiceImpl} is simply ignored.  Note that using this approach results
+ in "eager loading" behavior that you can't control.
+
+ <pre>
+     bindConstant().annotatedWith(ServerHost.class).to(args[0]);</pre>
+
+ Sets up a constant binding. Constant injections must always be annotated.
+ When a constant binding's value is a string, it is eligile for conversion to
+ all primitive types, to {@link Enum#valueOf(Class, String) all enums}, and to
+ {@link Class#forName class literals}. Conversions for other types can be
+ configured using {@link #convertToTypes(Matcher, TypeConverter)
+ convertToTypes()}.
+
+ <pre>
+   {@literal @}Color("red") Color red; // A member variable (field)
+    . . .
+     red = MyModule.class.getDeclaredField("red").getAnnotation(Color.class);
+     bind(Service.class).annotatedWith(red).to(RedService.class);</pre>
+
+ If your binding annotation has parameters you can apply different bindings to
+ different specific values of your annotation.  Getting your hands on the
+ right instance of the annotation is a bit of a pain -- one approach, shown
+ above, is to apply a prototype annotation to a field in your module class, so
+ that you can read this annotation instance and give it to Guice.
+
+ <pre>
+     bind(Service.class)
+         .annotatedWith(Names.named("blue"))
+         .to(BlueService.class);</pre>
+
+ Differentiating by names is a common enough use case that we provided a
+ standard annotation, {@link com.google.inject.name.Named @Named}.  Because of
+ Guice's library support, binding by name is quite easier than in the
+ arbitrary binding annotation case we just saw.  However, remember that these
+ names will live in a single flat namespace with all the other names used in
+ your application.
+
+ <pre>
+     Constructor<T> loneCtor = getLoneCtorFromServiceImplViaReflection();
+     bind(ServiceImpl.class)
+         .toConstructor(loneCtor);</pre>
+
+ In this example, we directly tell Guice which constructor to use in a concrete
+ class implementation. It means that we do not need to place {@literal @}Inject
+ on any of the constructors and that Guice treats the provided constructor as though
+ it were annotated so. It is useful for cases where you cannot modify existing
+ classes and is a bit simpler than using a {@link Provider}.
+
+ <p>The above list of examples is far from exhaustive.  If you can think of
+ how the concepts of one example might coexist with the concepts from another,
+ you can most likely weave the two together.  If the two concepts make no
+ sense with each other, you most likely won't be able to do it.  In a few
+ cases Guice will let something bogus slip by, and will then inform you of
+ the problems at runtime, as soon as you try to create your Injector.
+
+ <p>The other methods of Binder such as {@link #bindScope},
+ {@link #bindInterceptor}, {@link #install}, {@link #requestStaticInjection},
+ {@link #addError} and {@link #currentStage} are not part of the Binding EDSL;
+ you can learn how to use these in the usual way, from the method
+ documentation.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @author kevinb@google.com (Kevin Bourrillion)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Binder -->
+  <!-- start interface com.google.inject.Binding -->
+  <interface name="Binding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for this binding.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the scoped provider guice uses to fulfill requests for this
+ binding.
+
+ @throws UnsupportedOperationException when invoked on a {@link Binding}
+      created via {@link com.google.inject.spi.Elements#getElements}. This
+      method is only supported on {@link Binding}s returned from an injector.]]>
+      </doc>
+    </method>
+    <method name="acceptTargetVisitor" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;? super T, V&gt;"/>
+      <doc>
+      <![CDATA[Accepts a target visitor. Invokes the visitor method specific to this binding's target.
+
+ @param visitor to call back on
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="acceptScopingVisitor" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Accepts a scoping visitor. Invokes the visitor method specific to this binding's scoping.
+
+ @param visitor to call back on
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A mapping from a key (type and optional annotation) to the strategy for getting instances of the
+ type. This interface is part of the introspection API and is intended primarily for use by 
+ tools.
+
+ <p>Bindings are created in several ways:
+ <ul>
+     <li>Explicitly in a module, via {@code bind()} and {@code bindConstant()}
+         statements:
+ <pre>
+     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);
+     bindConstant().annotatedWith(ServerHost.class).to(args[0]);</pre></li>
+     <li>Implicitly by the Injector by following a type's {@link ImplementedBy
+         pointer} {@link ProvidedBy annotations} or by using its {@link Inject annotated} or
+         default constructor.</li>
+     <li>By converting a bound instance to a different type.</li>
+     <li>For {@link Provider providers}, by delegating to the binding for the provided type.</li>
+ </ul>
+
+
+ <p>They exist on both modules and on injectors, and their behaviour is different for each:
+ <ul>
+     <li><strong>Module bindings</strong> are incomplete and cannot be used to provide instances.
+         This is because the applicable scopes and interceptors may not be known until an injector
+         is created. From a tool's perspective, module bindings are like the injector's source
+         code. They can be inspected or rewritten, but this analysis must be done statically.</li>
+     <li><strong>Injector bindings</strong> are complete and valid and can be used to provide
+         instances. From a tools' perspective, injector bindings are like reflection for an
+         injector. They have full runtime information, including the complete graph of injections
+         necessary to satisfy a binding.</li>
+ </ul>
+
+ @param <T> the bound type. The injected is always assignable to this type.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Binding -->
+  <!-- start class com.google.inject.BindingAnnotation -->
+  <class name="BindingAnnotation"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates annotations which are used for binding. Only one such annotation
+ may apply to a single injection point. You must also annotate binder
+ annotations with {@code @Retention(RUNTIME)}. For example:
+
+ <pre>
+   {@code @}Retention(RUNTIME)
+   {@code @}Target({ FIELD, PARAMETER, METHOD })
+   {@code @}BindingAnnotation
+   public {@code @}interface Transactional {}
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.BindingAnnotation -->
+  <!-- start class com.google.inject.ConfigurationException -->
+  <class name="ConfigurationException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ConfigurationException" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a ConfigurationException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <method name="withPartialValue" return="com.google.inject.ConfigurationException"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="partialValue" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a copy of this configuration exception with the specified partial value.]]>
+      </doc>
+    </method>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getPartialValue" return="E"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a value that was only partially computed due to this exception. The caller can use
+ this while collecting additional configuration problems.
+
+ @return the partial value, or {@code null} if none was set. The type of the partial value is
+      specified by the throwing method.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Thrown when a programming error such as a misplaced annotation, illegal binding, or unsupported
+ scope is found. Clients should catch this exception, log it, and stop execution.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ConfigurationException -->
+  <!-- start class com.google.inject.CreationException -->
+  <class name="CreationException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="CreationException" type="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a CreationException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Thrown when errors occur while creating a {@link Injector}. Includes a list of encountered
+ errors. Clients should catch this exception, log it, and stop execution.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.CreationException -->
+  <!-- start class com.google.inject.Exposed -->
+  <class name="Exposed"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Acccompanies a {@literal @}{@link com.google.inject.Provides Provides} method annotation in a
+ private module to indicate that the provided binding is exposed.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Exposed -->
+  <!-- start class com.google.inject.Guice -->
+  <class name="Guice" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules. This is equivalent to
+ calling {@link #createInjector(Stage, Module...)} with Stage.DEVELOPMENT.
+
+ @throws CreationException if one or more errors occur during injector
+     construction]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules. This is equivalent to
+ calling {@link #createInjector(Stage, Iterable)} with Stage.DEVELOPMENT.
+
+ @throws CreationException if one or more errors occur during injector
+     creation]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules, in a given development
+ stage.
+
+ @throws CreationException if one or more errors occur during injector
+     creation.]]>
+      </doc>
+    </method>
+    <method name="createInjector" return="com.google.inject.Injector"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Creates an injector for the given set of modules, in a given development
+ stage.
+
+ @throws CreationException if one or more errors occur during injector
+     construction]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[The entry point to the Guice framework. Creates {@link Injector}s from
+ {@link Module}s.
+
+ <p>Guice supports a model of development that draws clear boundaries between
+ APIs, Implementations of these APIs, Modules which configure these
+ implementations, and finally Applications which consist of a collection of
+ Modules. It is the Application, which typically defines your {@code main()}
+ method, that bootstraps the Guice Injector using the {@code Guice} class, as
+ in this example:
+ <pre>
+     public class FooApplication {
+       public static void main(String[] args) {
+         Injector injector = Guice.createInjector(
+             new ModuleA(),
+             new ModuleB(),
+             . . .
+             new FooApplicationFlagsModule(args)
+         );
+
+         // Now just bootstrap the application and you're done
+         FooStarter starter = injector.getInstance(FooStarter.class);
+         starter.runApplication();
+       }
+     }
+ </pre>]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Guice -->
+  <!-- start class com.google.inject.ImplementedBy -->
+  <class name="ImplementedBy"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A pointer to the default implementation of a type.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ImplementedBy -->
+  <!-- start class com.google.inject.Inject -->
+  <class name="Inject"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates members of your implementation class (constructors, methods
+ and fields) into which the {@link Injector} should inject values.
+ The Injector fulfills injection requests for:
+
+ <ul>
+ <li>Every instance it constructs. The class being constructed must have
+ exactly one of its constructors marked with {@code @Inject} or must have a
+ constructor taking no parameters. The Injector then proceeds to perform
+ field and method injections.
+ 
+ <li>Pre-constructed instances passed to {@link Injector#injectMembers},
+ {@link com.google.inject.binder.LinkedBindingBuilder#toInstance(Object)} and
+ {@link com.google.inject.binder.LinkedBindingBuilder#toProvider(javax.inject.Provider)}.
+ In this case all constructors are, of course, ignored.
+
+ <li>Static fields and methods of classes which any {@link Module} has
+ specifically requested static injection for, using
+ {@link Binder#requestStaticInjection}.
+ </ul>
+
+ In all cases, a member can be injected regardless of its Java access
+ specifier (private, default, protected, public).
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Inject -->
+  <!-- start interface com.google.inject.Injector -->
+  <interface name="Injector"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="injectMembers"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
+ absence of an injectable constructor.
+
+ <p>Whenever Guice creates an instance, it performs this injection automatically (after first
+ performing constructor injection), so if you're able to let Guice create all your objects for
+ you, you'll never need to use this method.
+
+ @param instance to inject members on
+
+ @see Binder#getMembersInjector(Class) for a preferred alternative that supports checks before
+  run time]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}.
+
+ @param typeLiteral type to get members injector for
+ @see Binder#getMembersInjector(TypeLiteral) for an alternative that offers up front error
+  detection
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. When feasible, use {@link Binder#getMembersInjector(TypeLiteral)}
+ instead to get increased up front error detection.
+
+ @param type type to get members injector for
+ @see Binder#getMembersInjector(Class) for an alternative that offers up front error
+  detection
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getBindings" return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns this injector's <strong>explicit</strong> bindings.
+
+ <p>The returned map does not include bindings inherited from a {@link #getParent() parent
+ injector}, should one exist. The returned map is guaranteed to iterate (for example, with
+ its {@link Map#entrySet()} iterator) in the order of insertion. In other words, the order in
+ which bindings appear in user Modules.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.]]>
+      </doc>
+    </method>
+    <method name="getAllBindings" return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a snapshot of this injector's bindings, <strong>both explicit and
+ just-in-time</strong>. The returned map is immutable; it contains only the bindings that were
+ present when {@code getAllBindings()} was invoked. Subsequent calls may return a map with
+ additional just-in-time bindings.
+
+ <p>The returned map does not include bindings inherited from a {@link #getParent() parent
+ injector}, should one exist.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="getBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the binding for the given injection key. This will be an explicit bindings if the key
+ was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
+ be created if necessary.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+
+ @throws ConfigurationException if this injector cannot find or create the binding.]]>
+      </doc>
+    </method>
+    <method name="getBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the binding for the given type. This will be an explicit bindings if the injection key
+ was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
+ be created if necessary.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+
+ @throws ConfigurationException if this injector cannot find or create the binding.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getExistingBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the binding if it already exists, or null if does not exist. Unlike
+ {@link #getBinding(Key)}, this does not attempt to create just-in-time bindings
+ for keys that aren't bound.
+ 
+ <p> This method is part of the Guice SPI and is intended for use by tools and extensions.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="findBindingsByType" return="java.util.List&lt;com.google.inject.Binding&lt;T&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns all explicit bindings for {@code type}.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key. When feasible, avoid
+ using this method, in favor of having Guice inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @see Binder#getProvider(Key) for an alternative that offers up front error detection]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given type. When feasible, avoid
+ using this method, in favor of having Guice inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @see Binder#getProvider(Class) for an alternative that offers up front error detection]]>
+      </doc>
+    </method>
+    <method name="getInstance" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the appropriate instance for the given injection key; equivalent to {@code
+ getProvider(key).get()}. When feasible, avoid using this method, in favor of having Guice
+ inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @throws ProvisionException if there was a runtime failure while providing an instance.]]>
+      </doc>
+    </method>
+    <method name="getInstance" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the appropriate instance for the given injection type; equivalent to {@code
+ getProvider(type).get()}. When feasible, avoid using this method, in favor of having Guice
+ inject your dependencies ahead of time.
+
+ @throws ConfigurationException if this injector cannot find or create the provider.
+ @throws ProvisionException if there was a runtime failure while providing an instance.]]>
+      </doc>
+    </method>
+    <method name="getParent" return="com.google.inject.Injector"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns this injector's parent, or {@code null} if this is a top-level injector.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="createChildInjector" return="com.google.inject.Injector"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injector that inherits all state from this injector. All bindings, scopes,
+ interceptors and type converters are inherited -- they are visible to the child injector.
+ Elements of the child injector are not visible to its parent.
+
+ <p>Just-in-time bindings created for child injectors will be created in an ancestor injector
+ whenever possible. This allows for scoped instances to be shared between injectors. Use
+ explicit bindings to prevent bindings from being shared with the parent injector.  Optional
+ injections in just-in-time bindings (created in the parent injector) may be silently
+ ignored if the optional dependencies are from the child injector.
+
+ <p>No key may be bound by both an injector and one of its ancestors. This includes just-in-time
+ bindings. The lone exception is the key for {@code Injector.class}, which is bound by each
+ injector to itself.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="createChildInjector" return="com.google.inject.Injector"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a new injector that inherits all state from this injector. All bindings, scopes,
+ interceptors and type converters are inherited -- they are visible to the child injector.
+ Elements of the child injector are not visible to its parent.
+
+ <p>Just-in-time bindings created for child injectors will be created in an ancestor injector
+ whenever possible. This allows for scoped instances to be shared between injectors. Use
+ explicit bindings to prevent bindings from being shared with the parent injector.
+
+ <p>No key may be bound by both an injector and one of its ancestors. This includes just-in-time
+ bindings. The lone exception is the key for {@code Injector.class}, which is bound by each
+ injector to itself.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getScopeBindings" return="java.util.Map&lt;java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;, com.google.inject.Scope&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a map containing all scopes in the injector. The maps keys are scoping annotations
+ like {@code Singleton.class}, and the values are scope instances, such as {@code
+ Scopes.SINGLETON}. The returned map is immutable.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="getTypeConverterBindings" return="java.util.Set&lt;com.google.inject.spi.TypeConverterBinding&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a set containing all type converter bindings in the injector. The returned set is
+ immutable.
+
+ <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Builds the graphs of objects that make up your application. The injector tracks the dependencies
+ for each type and uses bindings to inject them. This is the core of Guice, although you rarely
+ interact with it directly. This "behind-the-scenes" operation is what distinguishes dependency
+ injection from its cousin, the service locator pattern.
+
+ <p>Contains several default bindings:
+
+ <ul>
+ <li>This {@link Injector} instance itself
+ <li>A {@code Provider<T>} for each binding of type {@code T}
+ <li>The {@link java.util.logging.Logger} for the class being injected
+ <li>The {@link Stage} in which the Injector was created
+ </ul>
+
+ Injectors are created using the facade class {@link Guice}.
+
+ <p>An injector can also {@link #injectMembers(Object) inject the dependencies} of
+ already-constructed instances. This can be used to interoperate with objects created by other
+ frameworks or services.
+
+ <p>Injectors can be {@link #createChildInjector(Iterable) hierarchical}. Child injectors inherit
+ the configuration of their parent injectors, but the converse does not hold.
+
+ <p>The injector's {@link #getBindings() internal bindings} are available for introspection. This
+ enables tools and extensions to operate on an injector reflectively.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Injector -->
+  <!-- start class com.google.inject.Key -->
+  <class name="Key" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Key" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo} annotated with
+ {@code @Bar}:
+
+ <p>{@code new Key<Foo>(Bar.class) {}}.]]>
+      </doc>
+    </constructor>
+    <constructor name="Key" type="java.lang.annotation.Annotation"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo} annotated with
+ {@code @Bar}:
+
+ <p>{@code new Key<Foo>(new Bar()) {}}.]]>
+      </doc>
+    </constructor>
+    <constructor name="Key"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new key. Derives the type from this class's type parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.
+
+ <p>Example usage for a binding of type {@code Foo}:
+
+ <p>{@code new Key<Foo>() {}}.]]>
+      </doc>
+    </constructor>
+    <method name="getTypeLiteral" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the key type.]]>
+      </doc>
+    </method>
+    <method name="getAnnotationType" return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the annotation type.]]>
+      </doc>
+    </method>
+    <method name="getAnnotation" return="java.lang.annotation.Annotation"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the annotation.]]>
+      </doc>
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation type.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Gets a key for an injection type and an annotation.]]>
+      </doc>
+    </method>
+    <method name="ofType" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new key of the specified type with the same annotation as this
+ key.
+
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="ofType" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a new key of the specified type with the same annotation as this
+ key.
+
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="ofType" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new key of the specified type with the same annotation as this
+ key.
+
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="hasAttributes" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if this key has annotation attributes.
+
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="withoutAttributes" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns this key without annotation attributes, i.e. with only the
+ annotation type.
+
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Binding key consisting of an injection type and an optional annotation.
+ Matches the type and annotation at a point of injection.
+
+ <p>For example, {@code Key.get(Service.class, Transactional.class)} will
+ match:
+
+ <pre>
+   {@literal @}Inject
+   public void setService({@literal @}Transactional Service service) {
+     ...
+   }
+ </pre>
+
+ <p>{@code Key} supports generic types via subclassing just like {@link
+ TypeLiteral}.
+
+ <p>Keys do not differentiate between primitive types (int, char, etc.) and
+ their correpsonding wrapper types (Integer, Character, etc.). Primitive
+ types will be replaced with their wrapper types when keys are created.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Key -->
+  <!-- start interface com.google.inject.MembersInjector -->
+  <interface name="MembersInjector"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="injectMembers"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
+ absence of an injectable constructor.
+
+ <p>Whenever Guice creates an instance, it performs this injection automatically (after first
+ performing constructor injection), so if you're able to let Guice create all your objects for
+ you, you'll never need to use this method.
+
+ @param instance to inject members on. May be {@code null}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Injects dependencies into the fields and methods on instances of type {@code T}. Ignores the
+ presence or absence of an injectable constructor.
+
+ @param <T> type to inject members of
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.MembersInjector -->
+  <!-- start interface com.google.inject.Module -->
+  <interface name="Module"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="configure"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Contributes bindings and other configurations for this module to {@code binder}.
+
+ <p><strong>Do not invoke this method directly</strong> to install submodules. Instead use
+ {@link Binder#install(Module)}, which ensures that {@link Provides provider methods} are
+ discovered.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A module contributes configuration information, typically interface
+ bindings, which will be used to create an {@link Injector}. A Guice-based
+ application is ultimately composed of little more than a set of
+ {@code Module}s and some bootstrapping code.
+
+ <p>Your Module classes can use a more streamlined syntax by extending
+ {@link AbstractModule} rather than implementing this interface directly.
+
+ <p>In addition to the bindings configured via {@link #configure}, bindings
+ will be created for all methods annotated with {@literal @}{@link Provides}.
+ Use scope and binding annotations on these methods to configure the
+ bindings.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Module -->
+  <!-- start class com.google.inject.OutOfScopeException -->
+  <class name="OutOfScopeException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="OutOfScopeException" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="OutOfScopeException" type="java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="OutOfScopeException" type="java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <doc>
+    <![CDATA[Thrown from {@link Provider#get} when an attempt is made to access a scoped
+ object while the scope in question is not currently active.
+
+ @author kevinb@google.com (Kevin Bourrillion)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.OutOfScopeException -->
+  <!-- start interface com.google.inject.PrivateBinder -->
+  <interface name="PrivateBinder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binder"/>
+    <method name="expose"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes the binding for {@code key} available to the enclosing environment]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to the enclosing environment. Use {@link
+ com.google.inject.binder.AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to the enclosing environment. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="withSource" return="com.google.inject.PrivateBinder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <method name="skipSources" return="com.google.inject.PrivateBinder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="classesToSkip" type="java.lang.Class[]"/>
+    </method>
+    <doc>
+    <![CDATA[Returns a binder whose configuration information is hidden from its environment by default. See
+ {@link com.google.inject.PrivateModule PrivateModule} for details.
+ 
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.PrivateBinder -->
+  <!-- start class com.google.inject.PrivateModule -->
+  <class name="PrivateModule" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Module"/>
+    <constructor name="PrivateModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="true"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="configure"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates bindings and other configurations private to this module. Use {@link #expose(Class)
+ expose()} to make the bindings in this module available externally.]]>
+      </doc>
+    </method>
+    <method name="expose"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Makes the binding for {@code key} available to other modules and the injector.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to other modules and the injector. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="expose" return="com.google.inject.binder.AnnotatedElementBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Makes a binding for {@code type} available to other modules and the injector. Use {@link
+ AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
+ binding annotation.]]>
+      </doc>
+    </method>
+    <method name="binder" return="com.google.inject.PrivateBinder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the current binder.]]>
+      </doc>
+    </method>
+    <method name="bindScope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[@see Binder#bindScope(Class, Scope)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Key)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#bind(Class)]]>
+      </doc>
+    </method>
+    <method name="bindConstant" return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#bindConstant()]]>
+      </doc>
+    </method>
+    <method name="install"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[@see Binder#install(Module)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[@see Binder#addError(String, Object[])]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Throwable)]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[@see Binder#addError(Message)]]>
+      </doc>
+    </method>
+    <method name="requestInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[@see Binder#requestInjection(Object)]]>
+      </doc>
+    </method>
+    <method name="requestStaticInjection"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="types" type="java.lang.Class[]"/>
+      <doc>
+      <![CDATA[@see Binder#requestStaticInjection(Class[])]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindInterceptor(com.google.inject.matcher.Matcher, com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Instructs Guice to require a binding to the given key.]]>
+      </doc>
+    </method>
+    <method name="requireBinding"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Instructs Guice to require a binding to the given type.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Key)]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getProvider(Class)]]>
+      </doc>
+    </method>
+    <method name="convertToTypes"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="converter" type="com.google.inject.spi.TypeConverter"/>
+      <doc>
+      <![CDATA[@see Binder#convertToTypes(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeConverter)]]>
+      </doc>
+    </method>
+    <method name="currentStage" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@see Binder#currentStage()]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(Class)]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@see Binder#getMembersInjector(TypeLiteral)]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"/>
+      <param name="listener" type="com.google.inject.spi.TypeListener"/>
+      <doc>
+      <![CDATA[@see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener)]]>
+      </doc>
+    </method>
+    <method name="bindListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="bindingMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.Binding&lt;?&gt;&gt;"/>
+      <param name="listeners" type="com.google.inject.spi.ProvisionListener[]"/>
+      <doc>
+      <![CDATA[@see Binder#bindListener(Matcher, ProvisionListener...)]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A module whose configuration information is hidden from its environment by default. Only bindings
+ that are explicitly exposed will be available to other modules and to the users of the injector.
+ This module may expose the bindings it creates and the bindings of the modules it installs.
+
+ <p>A private module can be nested within a regular module or within another private module using
+ {@link Binder#install install()}.  Its bindings live in a new environment that inherits bindings,
+ type converters, scopes, and interceptors from the surrounding ("parent") environment.  When you
+ nest multiple private modules, the result is a tree of environments where the injector's
+ environment is the root.
+
+ <p>Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link
+ com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link
+ Exposed} annotation:
+
+ <pre>
+ public class FooBarBazModule extends PrivateModule {
+   protected void configure() {
+     bind(Foo.class).to(RealFoo.class);
+     expose(Foo.class);
+
+     install(new TransactionalBarModule());
+     expose(Bar.class).annotatedWith(Transactional.class);
+
+     bind(SomeImplementationDetail.class);
+     install(new MoreImplementationDetailsModule());
+   }
+
+   {@literal @}Provides {@literal @}Exposed
+   public Baz provideBaz() {
+     return new SuperBaz();
+   }
+ }
+ </pre>
+
+ <p>Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent
+ injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the
+ root environment. Such bindings are shared among all environments in the tree.
+ 
+ <p>The scope of a binding is constrained to its environment. A singleton bound in a private
+ module will be unique to its environment. But a binding for the same type in a different private
+ module will yield a different instance.
+
+ <p>A shared binding that injects the {@code Injector} gets the root injector, which only has
+ access to bindings in the root environment. An explicit binding that injects the {@code Injector}
+ gets access to all bindings in the child environment.
+
+ <p>To promote a just-in-time binding to an explicit binding, bind it:
+ <pre>
+   bind(FooImpl.class);
+ </pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.PrivateModule -->
+  <!-- start class com.google.inject.ProvidedBy -->
+  <class name="ProvidedBy"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A pointer to the default provider type for a type.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ProvidedBy -->
+  <!-- start interface com.google.inject.Provider -->
+  <interface name="Provider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="javax.inject.Provider&lt;T&gt;"/>
+    <method name="get" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Provides an instance of {@code T}. Must never return {@code null}.
+
+ @throws OutOfScopeException when an attempt is made to access a scoped object while the scope
+     in question is not currently active
+ @throws ProvisionException if an instance cannot be provided. Such exceptions include messages
+     and throwables to describe why provision failed.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An object capable of providing instances of type {@code T}. Providers are used in numerous ways
+ by Guice:
+
+ <ul>
+ <li>When the default means for obtaining instances (an injectable or parameterless constructor)
+ is insufficient for a particular binding, the module can specify a custom {@code Provider}
+ instead, to control exactly how Guice creates or obtains instances for the binding.
+
+ <li>An implementation class may always choose to have a {@code Provider<T>} instance injected,
+ rather than having a {@code T} injected directly.  This may give you access to multiple
+ instances, instances you wish to safely mutate and discard, instances which are out of scope
+ (e.g. using a {@code @RequestScoped} object from within a {@code @SessionScoped} object), or
+ instances that will be initialized lazily.
+
+ <li>A custom {@link Scope} is implemented as a decorator of {@code Provider<T>}, which decides
+ when to delegate to the backing provider and when to provide the instance some other way.
+
+ <li>The {@link Injector} offers access to the {@code Provider<T>} it uses to fulfill requests
+ for a given key, via the {@link Injector#getProvider} methods.
+ </ul>
+
+ @param <T> the type of object this provides
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Provider -->
+  <!-- start class com.google.inject.Provides -->
+  <class name="Provides"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates methods of a {@link Module} to create a provider method binding. The method's return
+ type is bound to its returned value. Guice will pass dependencies to the method as parameters.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Provides -->
+  <!-- start class com.google.inject.ProvisionException -->
+  <class name="ProvisionException" extends="java.lang.RuntimeException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ProvisionException" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Creates a ProvisionException containing {@code messages}.]]>
+      </doc>
+    </constructor>
+    <constructor name="ProvisionException" type="java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="ProvisionException" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getErrorMessages" return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns messages for the errors that caused this exception.]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Indicates that there was a runtime failure while providing an instance.
+
+ @author kevinb@google.com (Kevin Bourrillion)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ProvisionException -->
+  <!-- start interface com.google.inject.Scope -->
+  <interface name="Scope"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="scope" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <param name="unscoped" type="com.google.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Scopes a provider. The returned provider returns objects from this scope.
+ If an object does not exist in this scope, the provider can use the given
+ unscoped provider to retrieve one.
+
+ <p>Scope implementations are strongly encouraged to override
+ {@link Object#toString} in the returned provider and include the backing
+ provider's {@code toString()} output.
+
+ @param key binding key
+ @param unscoped locates an instance when one doesn't already exist in this
+  scope.
+ @return a new provider which only delegates to the given unscoped provider
+  when an instance of the requested object doesn't already exist in this
+  scope]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[A short but useful description of this scope.  For comparison, the standard
+ scopes that ship with guice use the descriptions
+ {@code "Scopes.SINGLETON"}, {@code "ServletScopes.SESSION"} and
+ {@code "ServletScopes.REQUEST"}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A scope is a level of visibility that instances provided by Guice may have.
+ By default, an instance created by the {@link Injector} has <i>no scope</i>,
+ meaning it has no state from the framework's perspective -- the
+ {@code Injector} creates it, injects it once into the class that required it,
+ and then immediately forgets it. Associating a scope with a particular
+ binding allows the created instance to be "remembered" and possibly used
+ again for other injections.
+
+ <p>An example of a scope is {@link Scopes#SINGLETON}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.Scope -->
+  <!-- start class com.google.inject.ScopeAnnotation -->
+  <class name="ScopeAnnotation"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates annotations which are used for scoping. Only one such annotation
+ may apply to a single implementation class. You must also annotate scope
+ annotations with {@code @Retention(RUNTIME)}. For example:
+
+ <pre>
+   {@code @}Retention(RUNTIME)
+   {@code @}Target(TYPE, METHOD)
+   {@code @}ScopeAnnotation
+   public {@code @}interface SessionScoped {}
+ </pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.ScopeAnnotation -->
+  <!-- start class com.google.inject.Scopes -->
+  <class name="Scopes" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="isSingleton" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns true if {@code binding} is singleton-scoped. If the binding is a {@link
+ com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it
+ was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will
+ also true if the target binding is singleton-scoped.
+
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="isScoped" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <param name="scope" type="com.google.inject.Scope"/>
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns true if {@code binding} has the given scope. If the binding is a {@link
+ com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it
+ was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will
+ also true if the target binding has the given scope.
+
+ @param binding binding to check
+ @param scope scope implementation instance
+ @param scopeAnnotation scope annotation class]]>
+      </doc>
+    </method>
+    <method name="isCircularProxy" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="object" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns true if the object is a proxy for a circular dependency,
+ constructed by Guice because it encountered a circular dependency. Scope
+ implementations should be careful to <b>not cache circular proxies</b>,
+ because the proxies are not intended for general purpose use. (They are
+ designed just to fulfill the immediate injection, not all injections.
+ Caching them can lead to IllegalArgumentExceptions or ClassCastExceptions.)]]>
+      </doc>
+    </method>
+    <field name="SINGLETON" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[One instance per {@link Injector}. Also see {@code @}{@link Singleton}.]]>
+      </doc>
+    </field>
+    <field name="NO_SCOPE" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[No scope; the same as not applying any scope at all.  Each time the
+ Injector obtains an instance of an object with "no scope", it injects this
+ instance then immediately forgets it.  When the next request for the same
+ binding arrives it will need to obtain the instance over again.
+
+ <p>This exists only in case a class has been annotated with a scope
+ annotation such as {@link Singleton @Singleton}, and you need to override
+ this to "no scope" in your binding.
+
+ @since 2.0]]>
+      </doc>
+    </field>
+    <doc>
+    <![CDATA[Built-in scope implementations.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Scopes -->
+  <!-- start class com.google.inject.Singleton -->
+  <class name="Singleton"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want only one instance
+ (per {@link Injector}) to be reused for all injections for that binding.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Singleton -->
+  <!-- start class com.google.inject.Stage -->
+  <class name="Stage" extends="java.lang.Enum&lt;com.google.inject.Stage&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.Stage[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.Stage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[The stage we're running in.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.Stage -->
+  <!-- start class com.google.inject.TypeLiteral -->
+  <class name="TypeLiteral" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="TypeLiteral"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Constructs a new type literal. Derives represented class from type
+ parameter.
+
+ <p>Clients create an empty anonymous subclass. Doing so embeds the type
+ parameter in the anonymous class's type hierarchy so we can reconstitute it
+ at runtime despite erasure.]]>
+      </doc>
+    </constructor>
+    <method name="getRawType" return="java.lang.Class&lt;? super T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the raw (non-generic) type for this type.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getType" return="java.lang.reflect.Type"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets underlying {@code Type} instance.]]>
+      </doc>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Gets type literal for the given {@code Type} instance.]]>
+      </doc>
+    </method>
+    <method name="get" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Gets type literal for the given {@code Class} instance.]]>
+      </doc>
+    </method>
+    <method name="getSupertype" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="supertype" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns the generic form of {@code supertype}. For example, if this is {@code
+ ArrayList<String>}, this returns {@code Iterable<String>} given the input {@code
+ Iterable.class}.
+
+ @param supertype a superclass of, or interface implemented by, this.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getFieldType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="field" type="java.lang.reflect.Field"/>
+      <doc>
+      <![CDATA[Returns the resolved generic type of {@code field}.
+
+ @param field a field defined by this or any superclass.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getParameterTypes" return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodOrConstructor" type="java.lang.reflect.Member"/>
+      <doc>
+      <![CDATA[Returns the resolved generic parameter types of {@code methodOrConstructor}.
+
+ @param methodOrConstructor a method or constructor defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getExceptionTypes" return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodOrConstructor" type="java.lang.reflect.Member"/>
+      <doc>
+      <![CDATA[Returns the resolved generic exception types thrown by {@code constructor}.
+
+ @param methodOrConstructor a method or constructor defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getReturnType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="method" type="java.lang.reflect.Method"/>
+      <doc>
+      <![CDATA[Returns the resolved generic return type of {@code method}.
+
+ @param method a method defined by this or any supertype.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Represents a generic type {@code T}. Java doesn't yet provide a way to
+ represent generic types, so this class does. Forces clients to create a
+ subclass of this class which enables retrieval the type information even at
+ runtime.
+
+ <p>For example, to create a type literal for {@code List<String>}, you can
+ create an empty anonymous inner class:
+
+ <p>
+ {@code TypeLiteral<List<String>> list = new TypeLiteral<List<String>>() {};}
+
+ <p>Along with modeling generic types, this class can resolve type parameters.
+ For example, to figure out what type {@code keySet()} returns on a {@code
+ Map<Integer, String>}, use this code:<pre>   {@code
+
+   TypeLiteral<Map<Integer, String>> mapType
+       = new TypeLiteral<Map<Integer, String>>() {};
+   TypeLiteral<?> keySetType
+       = mapType.getReturnType(Map.class.getMethod("keySet"));
+   System.out.println(keySetType); // prints "Set<Integer>"}</pre>
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.TypeLiteral -->
+</package>
+<package name="com.google.inject.assistedinject">
+  <!-- start class com.google.inject.assistedinject.Assisted -->
+  <class name="Assisted"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates an injected parameter or field whose value comes from an argument to a factory method.
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.Assisted -->
+  <!-- start class com.google.inject.assistedinject.AssistedInject -->
+  <class name="AssistedInject"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[<p>
+ When used in tandem with {@link FactoryModuleBuilder}, constructors annotated with 
+ {@code @AssistedInject} indicate that multiple constructors can be injected, each with different
+ parameters. AssistedInject annotations should not be mixed with {@literal @}{@link Inject}
+ annotations. The assisted parameters must exactly match one corresponding factory method within
+ the factory interface, but the parameters do not need to be in the same order. Constructors
+ annotated with AssistedInject <b>are</b> created by Guice and receive all the benefits
+ (such as AOP).
+ 
+ <p>
+ <strong>Obsolete Usage:</strong> When used in tandem with {@link FactoryProvider}, constructors
+ annotated with {@code @AssistedInject} trigger a "backwards compatibility mode". The assisted
+ parameters must exactly match one corresponding factory method within the factory interface and
+ all must be in the same order as listed in the factory. In this backwards compatable mode,
+ constructors annotated with AssistedInject <b>are not</b> created by Guice and thus receive
+ none of the benefits.
+ 
+ <p>
+ Constructor parameters must be either supplied by the factory interface and marked with
+ <code>@Assisted</code>, or they must be injectable.
+ 
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.AssistedInject -->
+  <!-- start interface com.google.inject.assistedinject.AssistedInjectBinding -->
+  <interface name="AssistedInjectBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the {@link Key} for the factory binding.]]>
+      </doc>
+    </method>
+    <method name="getAssistedMethods" return="java.util.Collection&lt;com.google.inject.assistedinject.AssistedMethod&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns an {@link AssistedMethod} for each method in the factory.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding for a factory created by FactoryModuleBuilder.
+ 
+ @param <T> The fully qualified type of the factory.
+  
+ @since 3.0
+ @author ramakrishna@google.com (Ramakrishna Rajanna)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.assistedinject.AssistedInjectBinding -->
+  <!-- start interface com.google.inject.assistedinject.AssistedInjectTargetVisitor -->
+  <interface name="AssistedInjectTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="assistedInjectBinding" type="com.google.inject.assistedinject.AssistedInjectBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visits an {@link AssistedInjectBinding} created through {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A visitor for the AssistedInject extension.
+ <p>
+ If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ {@link FactoryModuleBuilder} will be visited through this interface.
+
+ @since 3.0
+ @author ramakrishna@google.com (Ramakrishna Rajanna)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.assistedinject.AssistedInjectTargetVisitor -->
+  <!-- start interface com.google.inject.assistedinject.AssistedMethod -->
+  <interface name="AssistedMethod"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getFactoryMethod" return="java.lang.reflect.Method"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the factory method that is being assisted.]]>
+      </doc>
+    </method>
+    <method name="getImplementationType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the implementation type that will be created when the method is
+ used.]]>
+      </doc>
+    </method>
+    <method name="getImplementationConstructor" return="java.lang.reflect.Constructor&lt;?&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the constructor that will be used to construct instances of the 
+ implementation.]]>
+      </doc>
+    </method>
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all non-assisted dependencies required to construct and inject
+ the implementation.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Details about how a method in an assisted inject factory will be assisted.
+ 
+ @since 3.0
+ @author ramakrishna@google.com (Ramakrishna Rajanna)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.assistedinject.AssistedMethod -->
+  <!-- start class com.google.inject.assistedinject.FactoryModuleBuilder -->
+  <class name="FactoryModuleBuilder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="FactoryModuleBuilder"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.Key&lt;T&gt;"/>
+      <param name="target" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="implement" return="com.google.inject.assistedinject.FactoryModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="com.google.inject.Key&lt;T&gt;"/>
+      <param name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="build" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryInterface" type="java.lang.Class&lt;F&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="build" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryInterface" type="com.google.inject.TypeLiteral&lt;F&gt;"/>
+      <doc>
+      <![CDATA[See the factory configuration examples at {@link FactoryModuleBuilder}.]]>
+      </doc>
+    </method>
+    <method name="build" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryInterface" type="com.google.inject.Key&lt;F&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[Provides a factory that combines the caller's arguments with injector-supplied values to
+ construct objects.
+
+ <h3>Defining a factory</h3>
+ Create an interface whose methods return the constructed type, or any of its supertypes. The
+ method's parameters are the arguments required to build the constructed type.
+
+ <pre>public interface PaymentFactory {
+   Payment create(Date startDate, Money amount);
+ }</pre>
+
+ You can name your factory methods whatever you like, such as <i>create</i>, <i>createPayment</i>
+ or <i>newPayment</i>.
+
+ <h3>Creating a type that accepts factory parameters</h3>
+ {@code constructedType} is a concrete class with an {@literal @}{@link com.google.inject.Inject
+ Inject}-annotated constructor. In addition to injector-supplied parameters, the constructor
+ should have parameters that match each of the factory method's parameters. Each factory-supplied
+ parameter requires an {@literal @}{@link Assisted} annotation. This serves to document that the
+ parameter is not bound by your application's modules.
+
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted Date startDate</strong>,
+      <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }
+ }</pre>
+ 
+ <h3>Multiple factory methods for the same type</h3>
+ If the factory contains many methods that return the same type, you can create multiple
+ constructors in your concrete class, each constructor marked with with
+ {@literal @}{@link AssistedInject}, in order to match the different parameters types of the
+ factory methods. 
+ 
+ <pre>public interface PaymentFactory {
+    Payment create(Date startDate, Money amount);
+    Payment createWithoutDate(Money amount);
+ }
+ 
+ public class RealPayment implements Payment {
+  {@literal @}AssistedInject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+     <strong>{@literal @}Assisted Date startDate</strong>,
+     <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }
+   
+  {@literal @}AssistedInject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+     <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }   
+ }</pre> 
+
+ <h3>Configuring simple factories</h3>
+ In your {@link Module module}, install a {@code FactoryModuleBuilder} that creates the
+ factory:
+
+ <pre>install(new FactoryModuleBuilder()
+     .implement(Payment.class, RealPayment.class)
+     .build(PaymentFactory.class);</pre>
+
+ As a side-effect of this binding, Guice will inject the factory to initialize it for use. The
+ factory cannot be used until the injector has been initialized.
+ 
+ <h3>Configuring complex factories</h3>
+ Factories can create an arbitrary number of objects, one per each method.  Each factory
+ method can be configured using <code>.implement</code>.
+
+ <pre>public interface OrderFactory {
+    Payment create(Date startDate, Money amount);
+    Shipment create(Customer customer, Item item);
+    Receipt create(Payment payment, Shipment shipment);
+ }
+ 
+ [...]
+ 
+ install(new FactoryModuleBuilder()
+     .implement(Payment.class, RealPayment.class)
+     // excluding .implement for Shipment means the implementation class
+     // will be 'Shipment' itself, which is legal if it's not an interface.
+     .implement(Receipt.class, RealReceipt.class)
+     .build(OrderFactory.class);</pre>
+ </pre>
+
+ <h3>Using the factory</h3>
+ Inject your factory into your application classes. When you use the factory, your arguments
+ will be combined with values from the injector to construct an instance.
+
+ <pre>public class PaymentAction {
+   {@literal @}Inject private PaymentFactory paymentFactory;
+
+   public void doPayment(Money amount) {
+     Payment payment = paymentFactory.create(new Date(), amount);
+     payment.apply();
+   }
+ }</pre>
+
+ <h3>Making parameter types distinct</h3>
+ The types of the factory method's parameters must be distinct. To use multiple parameters of
+ the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the
+ parameters. The names must be applied to the factory method's parameters:
+
+ <pre>public interface PaymentFactory {
+   Payment create(
+       <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+       <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+       Money amount);
+ } </pre>
+
+ ...and to the concrete type's constructor parameters:
+
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+      <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+      <strong>{@literal @}Assisted</strong> Money amount) {
+     ...
+   }
+ }</pre>
+
+ <h3>Values are created by Guice</h3>
+ Returned factories use child injectors to create values. The values are eligible for method
+ interception. In addition, {@literal @}{@literal Inject} members will be injected before they are
+ returned.
+
+ <h3>More configuration options</h3>
+ In addition to simply specifying an implementation class for any returned type, factories' return
+ values can be automatic or can be configured to use annotations:
+ <p/>
+ If you just want to return the types specified in the factory, do not configure any
+ implementations:
+
+ <pre>public interface FruitFactory {
+   Apple getApple(Color color);
+ }
+ ...
+ protected void configure() {
+   install(new FactoryModuleBuilder().build(FruitFactory.class));
+ }</pre>
+
+ Note that any type returned by the factory in this manner needs to be an implementation class.
+ <p/>
+ To return two different implementations for the same interface from your factory, use binding
+ annotations on your return types:
+
+ <pre>interface CarFactory {
+   {@literal @}Named("fast") Car getFastCar(Color color);
+   {@literal @}Named("clean") Car getCleanCar(Color color);
+ }
+ ...
+ protected void configure() {
+   install(new FactoryModuleBuilder()
+       .implement(Car.class, Names.named("fast"), Porsche.class)
+       .implement(Car.class, Names.named("clean"), Prius.class)
+       .build(CarFactory.class));
+ }</pre>
+ 
+ <h3>Implementation limitations</h3>
+ As a limitation of the implementation, it is prohibited to declare a factory method that
+ accepts a {@code Provider} as one of its arguments.
+
+ @since 3.0
+ @author schmitt@google.com (Peter Schmitt)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.FactoryModuleBuilder -->
+  <!-- start class com.google.inject.assistedinject.FactoryProvider -->
+  <class name="FactoryProvider" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="use {@link FactoryModuleBuilder} instead.">
+    <implements name="com.google.inject.Provider&lt;F&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="newFactory" return="com.google.inject.Provider&lt;F&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryType" type="java.lang.Class&lt;F&gt;"/>
+      <param name="implementationType" type="java.lang.Class&lt;?&gt;"/>
+    </method>
+    <method name="newFactory" return="com.google.inject.Provider&lt;F&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="factoryType" type="com.google.inject.TypeLiteral&lt;F&gt;"/>
+      <param name="implementationType" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+    </method>
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="get" return="F"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[<strong>Obsolete.</strong> Prefer {@link FactoryModuleBuilder} for its more concise API and
+ additional capability.
+
+ <p>Provides a factory that combines the caller's arguments with injector-supplied values to
+ construct objects.
+
+ <h3>Defining a factory</h3>
+ Create an interface whose methods return the constructed type, or any of its supertypes. The
+ method's parameters are the arguments required to build the constructed type.
+ <pre>public interface PaymentFactory {
+   Payment create(Date startDate, Money amount);
+ }</pre>
+ You can name your factory methods whatever you like, such as <i>create</i>, <i>createPayment</i>
+ or <i>newPayment</i>.
+
+ <h3>Creating a type that accepts factory parameters</h3>
+ {@code constructedType} is a concrete class with an {@literal @}{@link Inject}-annotated
+ constructor. In addition to injector-supplied parameters, the constructor should have
+ parameters that match each of the factory method's parameters. Each factory-supplied parameter
+ requires an {@literal @}{@link Assisted} annotation. This serves to document that the parameter
+ is not bound by your application's modules.
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted Date startDate</strong>,
+      <strong>{@literal @}Assisted Money amount</strong>) {
+     ...
+   }
+ }</pre>
+ Any parameter that permits a null value should also be annotated {@code @Nullable}.
+
+ <h3>Configuring factories</h3>
+ In your {@link com.google.inject.Module module}, bind the factory interface to the returned
+ factory:
+ <pre>bind(PaymentFactory.class).toProvider(
+     FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));</pre>
+ As a side-effect of this binding, Guice will inject the factory to initialize it for use. The
+ factory cannot be used until the injector has been initialized.
+
+ <h3>Using the factory</h3>
+ Inject your factory into your application classes. When you use the factory, your arguments
+ will be combined with values from the injector to construct an instance.
+ <pre>public class PaymentAction {
+   {@literal @}Inject private PaymentFactory paymentFactory;
+
+   public void doPayment(Money amount) {
+     Payment payment = paymentFactory.create(new Date(), amount);
+     payment.apply();
+   }
+ }</pre>
+
+ <h3>Making parameter types distinct</h3>
+ The types of the factory method's parameters must be distinct. To use multiple parameters of
+ the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the
+ parameters. The names must be applied to the factory method's parameters:
+
+ <pre>public interface PaymentFactory {
+   Payment create(
+       <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+       <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+       Money amount);
+ } </pre>
+ ...and to the concrete type's constructor parameters:
+ <pre>public class RealPayment implements Payment {
+   {@literal @}Inject
+   public RealPayment(
+      CreditService creditService,
+      AuthService authService,
+      <strong>{@literal @}Assisted("startDate")</strong> Date startDate,
+      <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate,
+      <strong>{@literal @}Assisted</strong> Money amount) {
+     ...
+   }
+ }</pre>
+
+ <h3>Values are created by Guice</h3>
+ Returned factories use child injectors to create values. The values are eligible for method
+ interception. In addition, {@literal @}{@literal Inject} members will be injected before they are
+ returned.
+
+ <h3>Backwards compatibility using {@literal @}AssistedInject</h3>
+ Instead of the {@literal @}Inject annotation, you may annotate the constructed classes with
+ {@literal @}{@link AssistedInject}. This triggers a limited backwards-compatability mode.
+
+ <p>Instead of matching factory method arguments to constructor parameters using their names, the
+ <strong>parameters are matched by their order</strong>. The first factory method argument is
+ used for the first {@literal @}Assisted constructor parameter, etc.. Annotation names have no
+ effect.
+
+ <p>Returned values are <strong>not created by Guice</strong>. These types are not eligible for
+ method interception. They do receive post-construction member injection.
+
+ @param <F> The factory interface
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)
+ @author dtm@google.com (Daniel Martin)
+ 
+ @deprecated use {@link FactoryModuleBuilder} instead.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.assistedinject.FactoryProvider -->
+</package>
+<package name="com.google.inject.binder">
+  <!-- start interface com.google.inject.binder.AnnotatedBindingBuilder -->
+  <interface name="AnnotatedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"/>
+    <method name="annotatedWith" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedBindingBuilder -->
+  <!-- start interface com.google.inject.binder.AnnotatedConstantBindingBuilder -->
+  <interface name="AnnotatedConstantBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="annotatedWith" return="com.google.inject.binder.ConstantBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.binder.ConstantBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedConstantBindingBuilder -->
+  <!-- start interface com.google.inject.binder.AnnotatedElementBuilder -->
+  <interface name="AnnotatedElementBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="annotatedWith"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.AnnotatedElementBuilder -->
+  <!-- start interface com.google.inject.binder.ConstantBindingBuilder -->
+  <interface name="ConstantBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="int"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="long"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="boolean"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="double"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="float"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="short"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="char"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="byte"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <method name="to"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="E extends java.lang.Enum&lt;E&gt;"/>
+      <doc>
+      <![CDATA[Binds constant to the given value.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Binds to a constant value.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.ConstantBindingBuilder -->
+  <!-- start interface com.google.inject.binder.LinkedBindingBuilder -->
+  <interface name="LinkedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.binder.ScopedBindingBuilder"/>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="implementation" type="java.lang.Class&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="implementation" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetKey" type="com.google.inject.Key&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toInstance"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @see com.google.inject.Injector#injectMembers]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="provider" type="com.google.inject.Provider&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @see com.google.inject.Injector#injectMembers]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="provider" type="javax.inject.Provider&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @see com.google.inject.Injector#injectMembers]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerType" type="java.lang.Class&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerType" type="com.google.inject.TypeLiteral&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toProvider" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerKey" type="com.google.inject.Key&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="toConstructor" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructor" type="java.lang.reflect.Constructor&lt;S&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="toConstructor" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructor" type="java.lang.reflect.Constructor&lt;S&gt;"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;? extends S&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.LinkedBindingBuilder -->
+  <!-- start interface com.google.inject.binder.ScopedBindingBuilder -->
+  <interface name="ScopedBindingBuilder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="in"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="in"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <method name="asEagerSingleton"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Instructs the {@link com.google.inject.Injector} to eagerly initialize this
+ singleton-scoped binding upon creation. Useful for application
+ initialization logic.  See the EDSL examples at
+ {@link com.google.inject.Binder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link com.google.inject.Binder}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.binder.ScopedBindingBuilder -->
+</package>
+<package name="com.google.inject.grapher">
+  <!-- start class com.google.inject.grapher.AbstractInjectorGrapher -->
+  <class name="AbstractInjectorGrapher" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.InjectorGrapher"/>
+    <constructor name="AbstractInjectorGrapher"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="AbstractInjectorGrapher" type="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="graph"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="injector" type="com.google.inject.Injector"/>
+      <exception name="IOException" type="java.io.IOException"/>
+    </method>
+    <method name="graph"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="public"
+      deprecated="not deprecated">
+      <param name="injector" type="com.google.inject.Injector"/>
+      <param name="root" type="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"/>
+      <exception name="IOException" type="java.io.IOException"/>
+    </method>
+    <method name="reset"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Resets the state of the grapher before rendering a new graph.]]>
+      </doc>
+    </method>
+    <method name="newInterfaceNode"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.InterfaceNode"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Adds a new interface node to the graph.]]>
+      </doc>
+    </method>
+    <method name="newImplementationNode"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.ImplementationNode"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Adds a new implementation node to the graph.]]>
+      </doc>
+    </method>
+    <method name="newInstanceNode"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.InstanceNode"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Adds a new instance node to the graph.]]>
+      </doc>
+    </method>
+    <method name="newDependencyEdge"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.DependencyEdge"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Adds a new dependency edge to the graph.]]>
+      </doc>
+    </method>
+    <method name="newBindingEdge"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.BindingEdge"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Adds a new binding edge to the graph.]]>
+      </doc>
+    </method>
+    <method name="postProcess"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Performs any post processing required after all nodes and edges have been added.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Abstract injector grapher that builds the dependency graph but doesn't render it.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.AbstractInjectorGrapher -->
+  <!-- start class com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters -->
+  <class name="AbstractInjectorGrapher.GrapherParameters" extends="java.lang.Object"
+    abstract="false"
+    static="true" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GrapherParameters"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getRootKeySetCreator" return="com.google.inject.grapher.RootKeySetCreator"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setRootKeySetCreator" return="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="rootKeySetCreator" type="com.google.inject.grapher.RootKeySetCreator"/>
+    </method>
+    <method name="getAliasCreator" return="com.google.inject.grapher.AliasCreator"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setAliasCreator" return="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="aliasCreator" type="com.google.inject.grapher.AliasCreator"/>
+    </method>
+    <method name="getNodeCreator" return="com.google.inject.grapher.NodeCreator"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setNodeCreator" return="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="nodeCreator" type="com.google.inject.grapher.NodeCreator"/>
+    </method>
+    <method name="getEdgeCreator" return="com.google.inject.grapher.EdgeCreator"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setEdgeCreator" return="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="edgeCreator" type="com.google.inject.grapher.EdgeCreator"/>
+    </method>
+    <doc>
+    <![CDATA[Parameters used to override default settings of the grapher.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters -->
+  <!-- start class com.google.inject.grapher.Alias -->
+  <class name="Alias" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Alias" type="com.google.inject.grapher.NodeId, com.google.inject.grapher.NodeId"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getFromId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getToId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Alias between two nodes. Causes the 'from' node to be aliased with the 'to' node, which means
+ that the 'from' node is not rendered and all edges going to it instead go to the 'to' node.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.Alias -->
+  <!-- start interface com.google.inject.grapher.AliasCreator -->
+  <interface name="AliasCreator"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="createAliases" return="java.lang.Iterable&lt;com.google.inject.grapher.Alias&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bindings" type="java.lang.Iterable&lt;com.google.inject.Binding&lt;?&gt;&gt;"/>
+      <doc>
+      <![CDATA[Returns aliases for the given dependency graph. The aliases do not need to be transitively
+ resolved, i.e. it is valid to return an alias (X to Y) and an alias (Y to Z). It is the
+ responsibility of the caller to resolve this to (X to Z) and (Y to Z).
+
+ @param bindings bindings that make up the dependency graph
+ @return aliases that should be applied on the graph]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Creator of node aliases. Used by dependency graphers to merge nodes in the internal Guice graph
+ into a single node on the rendered graph.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.AliasCreator -->
+  <!-- start class com.google.inject.grapher.BindingEdge -->
+  <class name="BindingEdge" extends="com.google.inject.grapher.Edge"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="BindingEdge" type="com.google.inject.grapher.NodeId, com.google.inject.grapher.NodeId, com.google.inject.grapher.BindingEdge.Type"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getType" return="com.google.inject.grapher.BindingEdge.Type"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="obj" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="copy" return="com.google.inject.grapher.Edge"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="com.google.inject.grapher.NodeId"/>
+      <param name="toId" type="com.google.inject.grapher.NodeId"/>
+    </method>
+    <doc>
+    <![CDATA[Edge that connects an interface to the type or instance that is bound to implement it.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.BindingEdge -->
+  <!-- start class com.google.inject.grapher.BindingEdge.Type -->
+  <class name="BindingEdge.Type" extends="java.lang.Enum&lt;com.google.inject.grapher.BindingEdge.Type&gt;"
+    abstract="false"
+    static="true" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.BindingEdge.Type[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.BindingEdge.Type"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[Classification for what kind of binding this edge represents.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.BindingEdge.Type -->
+  <!-- start class com.google.inject.grapher.DefaultRootKeySetCreator -->
+  <class name="DefaultRootKeySetCreator" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.RootKeySetCreator"/>
+    <constructor name="DefaultRootKeySetCreator"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getRootKeys" return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injector" type="com.google.inject.Injector"/>
+    </method>
+    <doc>
+    <![CDATA[Root key set creator that starts with all types that are not Guice internal types or the
+ {@link Logger} type.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.DefaultRootKeySetCreator -->
+  <!-- start class com.google.inject.grapher.DependencyEdge -->
+  <class name="DependencyEdge" extends="com.google.inject.grapher.Edge"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="DependencyEdge" type="com.google.inject.grapher.NodeId, com.google.inject.grapher.NodeId, com.google.inject.spi.InjectionPoint"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getInjectionPoint" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="obj" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="copy" return="com.google.inject.grapher.Edge"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="com.google.inject.grapher.NodeId"/>
+      <param name="toId" type="com.google.inject.grapher.NodeId"/>
+    </method>
+    <doc>
+    <![CDATA[Edge from a class or {@link InjectionPoint} to the interface node that will satisfy the
+ dependency.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.DependencyEdge -->
+  <!-- start class com.google.inject.grapher.Edge -->
+  <class name="Edge" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Edge" type="com.google.inject.grapher.NodeId, com.google.inject.grapher.NodeId"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getFromId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getToId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="obj" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="copy" return="com.google.inject.grapher.Edge"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="fromId" type="com.google.inject.grapher.NodeId"/>
+      <param name="toId" type="com.google.inject.grapher.NodeId"/>
+      <doc>
+      <![CDATA[Returns a copy of the edge with new node IDs.
+
+ @param fromId new ID of the 'from' node
+ @param toId new ID of the 'to' node
+ @return copy of the edge with the new node IDs]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Edge in a guice dependency graph.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.Edge -->
+  <!-- start interface com.google.inject.grapher.EdgeCreator -->
+  <interface name="EdgeCreator"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getEdges" return="java.lang.Iterable&lt;com.google.inject.grapher.Edge&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bindings" type="java.lang.Iterable&lt;com.google.inject.Binding&lt;?&gt;&gt;"/>
+      <doc>
+      <![CDATA[Returns edges for the given dependency graph.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Creator of graph edges to render. All edges will be rendered on the graph after node aliasing is
+ performed.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.EdgeCreator -->
+  <!-- start class com.google.inject.grapher.ImplementationNode -->
+  <class name="ImplementationNode" extends="com.google.inject.grapher.Node"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ImplementationNode" type="com.google.inject.grapher.NodeId, java.lang.Object, java.util.Collection&lt;java.lang.reflect.Member&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getMembers" return="java.util.Collection&lt;java.lang.reflect.Member&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="obj" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="copy" return="com.google.inject.grapher.Node"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="id" type="com.google.inject.grapher.NodeId"/>
+    </method>
+    <doc>
+    <![CDATA[Node for types that have {@link Dependency}s and are bound to {@link InterfaceNode}s. These
+ nodes will often have fields for {@link Member}s that are {@link InjectionPoint}s.
+
+ @see DependencyEdge
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.ImplementationNode -->
+  <!-- start interface com.google.inject.grapher.InjectorGrapher -->
+  <interface name="InjectorGrapher"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="graph"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injector" type="com.google.inject.Injector"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Graphs the guice dependency graph for the given injector using default starting keys.]]>
+      </doc>
+    </method>
+    <method name="graph"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injector" type="com.google.inject.Injector"/>
+      <param name="root" type="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <doc>
+      <![CDATA[Graphs the guice dependency graph for the given injector using the given starting keys and
+ their transitive dependencies.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Guice injector grapher. Renders the guice dependency graph for an injector. It can render the
+ whole dependency graph or just transitive dependencies of a given set of nodes.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.InjectorGrapher -->
+  <!-- start class com.google.inject.grapher.InstanceNode -->
+  <class name="InstanceNode" extends="com.google.inject.grapher.Node"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="InstanceNode" type="com.google.inject.grapher.NodeId, java.lang.Object, java.lang.Object, java.lang.Iterable&lt;java.lang.reflect.Member&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getInstance" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getMembers" return="java.lang.Iterable&lt;java.lang.reflect.Member&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="obj" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="copy" return="com.google.inject.grapher.Node"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="id" type="com.google.inject.grapher.NodeId"/>
+    </method>
+    <doc>
+    <![CDATA[Node for instances. Used when a type is bound to an instance.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.InstanceNode -->
+  <!-- start class com.google.inject.grapher.InterfaceNode -->
+  <class name="InterfaceNode" extends="com.google.inject.grapher.Node"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="InterfaceNode" type="com.google.inject.grapher.NodeId, java.lang.Object"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="copy" return="com.google.inject.grapher.Node"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="id" type="com.google.inject.grapher.NodeId"/>
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="obj" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Node for an interface type that has been bound to an implementation class or instance.
+
+ @see BindingEdge
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.InterfaceNode -->
+  <!-- start interface com.google.inject.grapher.NameFactory -->
+  <interface name="NameFactory"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getMemberName" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <method name="getClassName" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getInstanceName" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+    </method>
+    <method name="getAnnotationName" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getSourceName" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+    </method>
+    <doc>
+    <![CDATA[Interface for a service that provides nice {@link String}s that we can
+ display in the graph for the types that come up in {@link Binding}s.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.NameFactory -->
+  <!-- start class com.google.inject.grapher.Node -->
+  <class name="Node" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Node" type="com.google.inject.grapher.NodeId, java.lang.Object"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="obj" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="copy" return="com.google.inject.grapher.Node"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="id" type="com.google.inject.grapher.NodeId"/>
+      <doc>
+      <![CDATA[Returns a copy of the node with a new ID.
+
+ @param id new ID of the node
+ @return copy of the node with a new ID]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Node in a guice dependency graph.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.Node -->
+  <!-- start interface com.google.inject.grapher.NodeCreator -->
+  <interface name="NodeCreator"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getNodes" return="java.lang.Iterable&lt;com.google.inject.grapher.Node&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bindings" type="java.lang.Iterable&lt;com.google.inject.Binding&lt;?&gt;&gt;"/>
+      <doc>
+      <![CDATA[Returns nodes for the given dependency graph.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Creator of graph nodes.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.NodeCreator -->
+  <!-- start class com.google.inject.grapher.NodeId -->
+  <class name="NodeId" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="newTypeId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="newInstanceId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getKey" return="com.google.inject.Key&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="obj" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[ID of a node in the graph. An ID is given by a {@link Key} and a node type, which is used to
+ distinguish instances and implementation classes for the same key. For example
+ {@code bind(Integer.class).toInstance(42)} produces two nodes: an
+ interface node with the key of {@code Key<Integer>} and an instance node with the same
+ {@link Key} and value of 42.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.NodeId -->
+  <!-- start class com.google.inject.grapher.NodeId.NodeType -->
+  <class name="NodeId.NodeType" extends="java.lang.Enum&lt;com.google.inject.grapher.NodeId.NodeType&gt;"
+    abstract="false"
+    static="true" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.NodeId.NodeType[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.NodeId.NodeType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[Type of node.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.NodeId.NodeType -->
+  <!-- start interface com.google.inject.grapher.RootKeySetCreator -->
+  <interface name="RootKeySetCreator"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getRootKeys" return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Returns the set of starting keys to graph.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Creator of the default starting set of keys to graph. These keys and their transitive
+ dependencies will be graphed.
+
+ @author bojand@google.com (Bojan Djordjevic)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.RootKeySetCreator -->
+  <!-- start class com.google.inject.grapher.ShortNameFactory -->
+  <class name="ShortNameFactory" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.NameFactory"/>
+    <constructor name="ShortNameFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getMemberName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <method name="getAnnotationName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getClassName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+    </method>
+    <method name="getInstanceName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="java.lang.Object"/>
+    </method>
+    <method name="getSourceName" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="source" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a name for a Guice "source" object. This will typically be either
+ a {@link StackTraceElement} for when the binding is made to the instance,
+ or a {@link Method} when a provider method is used.]]>
+      </doc>
+    </method>
+    <method name="getFileString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="stackTraceElement" type="java.lang.StackTraceElement"/>
+    </method>
+    <method name="getMethodString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="method" type="java.lang.reflect.Method"/>
+    </method>
+    <doc>
+    <![CDATA[Reasonable implementation for {@link NameFactory}. Mostly takes various
+ {@link Object#toString()}s and strips package names out of them so that
+ they'll fit on the graph.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.ShortNameFactory -->
+  <!-- start class com.google.inject.grapher.TransitiveDependencyVisitor -->
+  <class name="TransitiveDependencyVisitor" extends="com.google.inject.spi.DefaultBindingTargetVisitor&lt;java.lang.Object, java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;&gt;"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="TransitiveDependencyVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConstructorBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InstanceBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;?&gt;"/>
+    </method>
+    <method name="visitOther" return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[{@link BindingTargetVisitor} that returns a {@link Collection} of the
+ {@link Key}s of each {@link Binding}'s dependencies. Used by
+ {@link InjectorGrapher} to walk the dependency graph from a starting set of
+ {@link Binding}s.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.TransitiveDependencyVisitor -->
+</package>
+<package name="com.google.inject.grapher.graphviz">
+  <!-- start class com.google.inject.grapher.graphviz.ArrowType -->
+  <class name="ArrowType" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.ArrowType[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.ArrowType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Arrow symbols that are available from Graphviz. These can be composed by
+ concatenation to make double arrows and such.
+ <p>
+ See: http://www.graphviz.org/doc/info/arrows.html
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.ArrowType -->
+  <!-- start class com.google.inject.grapher.graphviz.CompassPoint -->
+  <class name="CompassPoint" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.CompassPoint&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.CompassPoint[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.CompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Enum for the "compass point" values used to control where edge
+ end points appear on the graph.
+ <p>
+ See: http://www.graphviz.org/doc/info/attrs.html#k:portPos
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.CompassPoint -->
+  <!-- start class com.google.inject.grapher.graphviz.EdgeStyle -->
+  <class name="EdgeStyle" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.EdgeStyle&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.EdgeStyle[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.EdgeStyle"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Styles for edges.
+ <p>
+ See: http://www.graphviz.org/doc/info/attrs.html#k:style
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.EdgeStyle -->
+  <!-- start class com.google.inject.grapher.graphviz.GraphvizEdge -->
+  <class name="GraphvizEdge" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GraphvizEdge" type="com.google.inject.grapher.NodeId, com.google.inject.grapher.NodeId"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getHeadNodeId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getHeadPortId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setHeadPortId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="headPortId" type="java.lang.String"/>
+    </method>
+    <method name="getHeadCompassPoint" return="com.google.inject.grapher.graphviz.CompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setHeadCompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="headCompassPoint" type="com.google.inject.grapher.graphviz.CompassPoint"/>
+    </method>
+    <method name="getArrowHead" return="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setArrowHead"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="arrowHead" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"/>
+    </method>
+    <method name="getTailNodeId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTailPortId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setTailPortId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="tailPortId" type="java.lang.String"/>
+    </method>
+    <method name="getTailCompassPoint" return="com.google.inject.grapher.graphviz.CompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setTailCompassPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="tailCompassPoint" type="com.google.inject.grapher.graphviz.CompassPoint"/>
+    </method>
+    <method name="getArrowTail" return="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setArrowTail"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="arrowTail" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"/>
+    </method>
+    <method name="getStyle" return="com.google.inject.grapher.graphviz.EdgeStyle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setStyle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="style" type="com.google.inject.grapher.graphviz.EdgeStyle"/>
+    </method>
+    <doc>
+    <![CDATA[Data object to encapsulate the attributes of Graphviz edges that we're
+ interested in drawing.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.GraphvizEdge -->
+  <!-- start class com.google.inject.grapher.graphviz.GraphvizGrapher -->
+  <class name="GraphvizGrapher" extends="com.google.inject.grapher.AbstractInjectorGrapher"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="reset"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="setOut"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="out" type="java.io.PrintWriter"/>
+    </method>
+    <method name="setRankdir"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="rankdir" type="java.lang.String"/>
+    </method>
+    <method name="postProcess"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="getGraphAttributes" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="start"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="finish"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="renderNode"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"/>
+    </method>
+    <method name="getNodeAttributes" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"/>
+    </method>
+    <method name="getNodeLabel" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.graphviz.GraphvizNode"/>
+      <doc>
+      <![CDATA[Creates the "label" for a node. This is a string of HTML that defines a
+ table with a heading at the top and (in the case of
+ {@link ImplementationNode}s) rows for each of the member fields.]]>
+      </doc>
+    </method>
+    <method name="renderEdge"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"/>
+    </method>
+    <method name="getEdgeAttributes" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge"/>
+    </method>
+    <method name="getArrowString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="arrows" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"/>
+      <doc>
+      <![CDATA[Turns a {@link List} of {@link ArrowType}s into a {@link String} that
+ represents combining them. With Graphviz, that just means concatenating
+ them.]]>
+      </doc>
+    </method>
+    <method name="getEdgeEndPoint" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="nodeId" type="java.lang.String"/>
+      <param name="portId" type="java.lang.String"/>
+      <param name="compassPoint" type="com.google.inject.grapher.graphviz.CompassPoint"/>
+    </method>
+    <method name="htmlEscape" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="str" type="java.lang.String"/>
+    </method>
+    <method name="htmlEscape" return="java.util.List&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="elements" type="java.util.List&lt;java.lang.String&gt;"/>
+    </method>
+    <method name="newInterfaceNode"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.InterfaceNode"/>
+    </method>
+    <method name="newImplementationNode"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.ImplementationNode"/>
+    </method>
+    <method name="newInstanceNode"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="node" type="com.google.inject.grapher.InstanceNode"/>
+    </method>
+    <method name="newDependencyEdge"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.DependencyEdge"/>
+    </method>
+    <method name="newBindingEdge"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="edge" type="com.google.inject.grapher.BindingEdge"/>
+    </method>
+    <doc>
+    <![CDATA[{@link InjectorGrapher} implementation that writes out a Graphviz DOT file of the graph.
+ Dependencies are bound in {@link GraphvizModule}.
+ <p>
+ Specify the {@link PrintWriter} to output to with {@link #setOut(PrintWriter)}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.GraphvizGrapher -->
+  <!-- start class com.google.inject.grapher.graphviz.GraphvizModule -->
+  <class name="GraphvizModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GraphvizModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Module that provides classes needed by {@link GraphvizGrapher}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.GraphvizModule -->
+  <!-- start class com.google.inject.grapher.graphviz.GraphvizNode -->
+  <class name="GraphvizNode" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GraphvizNode" type="com.google.inject.grapher.NodeId"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getNodeId" return="com.google.inject.grapher.NodeId"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getShape" return="com.google.inject.grapher.graphviz.NodeShape"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setShape"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="shape" type="com.google.inject.grapher.graphviz.NodeShape"/>
+    </method>
+    <method name="getStyle" return="com.google.inject.grapher.graphviz.NodeStyle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setStyle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="style" type="com.google.inject.grapher.graphviz.NodeStyle"/>
+    </method>
+    <method name="getTitle" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setTitle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="title" type="java.lang.String"/>
+    </method>
+    <method name="getSubtitles" return="java.util.List&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="addSubtitle"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="position" type="int"/>
+      <param name="subtitle" type="java.lang.String"/>
+    </method>
+    <method name="getHeaderTextColor" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setHeaderTextColor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="headerTextColor" type="java.lang.String"/>
+    </method>
+    <method name="getHeaderBackgroundColor" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setHeaderBackgroundColor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="headerBackgroundColor" type="java.lang.String"/>
+    </method>
+    <method name="addField"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="portId" type="java.lang.String"/>
+      <param name="title" type="java.lang.String"/>
+    </method>
+    <method name="getFields" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getIdentifier" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="setIdentifier"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="identifier" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[Data object to encapsulate the attributes of Graphviz nodes that we're
+ interested in drawing.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.GraphvizNode -->
+  <!-- start class com.google.inject.grapher.graphviz.NodeShape -->
+  <class name="NodeShape" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.NodeShape&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.NodeShape[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.NodeShape"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Enum for the shapes that are most interesting for Guice graphing.
+ <p>
+ See: http://www.graphviz.org/doc/info/shapes.html
+ 
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.NodeShape -->
+  <!-- start class com.google.inject.grapher.graphviz.NodeStyle -->
+  <class name="NodeStyle" extends="java.lang.Enum&lt;com.google.inject.grapher.graphviz.NodeStyle&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.grapher.graphviz.NodeStyle[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.grapher.graphviz.NodeStyle"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Styles for nodes. Similar to {@link EdgeStyle} but with a few more options.
+ <p>
+ See: http://www.graphviz.org/doc/info/attrs.html#k:style
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.NodeStyle -->
+  <!-- start interface com.google.inject.grapher.graphviz.PortIdFactory -->
+  <interface name="PortIdFactory"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getPortId" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <doc>
+    <![CDATA[Interface for a service that returns Graphviz port IDs, used for naming the
+ rows in {@link ImplementationNode}-displaying {@link GraphvizNode}s.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.grapher.graphviz.PortIdFactory -->
+  <!-- start class com.google.inject.grapher.graphviz.PortIdFactoryImpl -->
+  <class name="PortIdFactoryImpl" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.grapher.graphviz.PortIdFactory"/>
+    <constructor name="PortIdFactoryImpl"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getPortId" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="member" type="java.lang.reflect.Member"/>
+    </method>
+    <doc>
+    <![CDATA[Implementation of {@link PortIdFactory}. Bound in {@link GraphvizModule}.
+
+ @author phopkins@gmail.com (Pete Hopkins)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.grapher.graphviz.PortIdFactoryImpl -->
+</package>
+<package name="com.google.inject.jndi">
+  <!-- start class com.google.inject.jndi.JndiIntegration -->
+  <class name="JndiIntegration" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="fromJndi" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a provider which looks up objects in JNDI using the given name.
+ Example usage:
+
+ <pre>
+ bind(DataSource.class).toProvider(fromJndi(DataSource.class, "java:..."));
+ </pre>]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Integrates Guice with JNDI. Requires a binding to 
+ {@link javax.naming.Context}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.jndi.JndiIntegration -->
+</package>
+<package name="com.google.inject.matcher">
+  <!-- start class com.google.inject.matcher.AbstractMatcher -->
+  <class name="AbstractMatcher" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.matcher.Matcher&lt;T&gt;"/>
+    <constructor name="AbstractMatcher"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="and" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+    </method>
+    <method name="or" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[Implements {@code and()} and {@code or()}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.matcher.AbstractMatcher -->
+  <!-- start interface com.google.inject.matcher.Matcher -->
+  <interface name="Matcher"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="matches" return="boolean"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="T"/>
+      <doc>
+      <![CDATA[Returns {@code true} if this matches {@code t}, {@code false} otherwise.]]>
+      </doc>
+    </method>
+    <method name="and" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new matcher which returns {@code true} if both this and the
+ given matcher return {@code true}.]]>
+      </doc>
+    </method>
+    <method name="or" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new matcher which returns {@code true} if either this or the
+ given matcher return {@code true}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Returns {@code true} or {@code false} for a given input.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.matcher.Matcher -->
+  <!-- start class com.google.inject.matcher.Matchers -->
+  <class name="Matchers" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="any" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a matcher which matches any input.]]>
+      </doc>
+    </method>
+    <method name="not" return="com.google.inject.matcher.Matcher&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="p" type="com.google.inject.matcher.Matcher&lt;? super T&gt;"/>
+      <doc>
+      <![CDATA[Inverts the given matcher.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches elements (methods, classes, etc.)
+ with a given annotation.]]>
+      </doc>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches elements (methods, classes, etc.)
+ with a given annotation.]]>
+      </doc>
+    </method>
+    <method name="subclassesOf" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="superclass" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches subclasses of the given type (as well as
+ the given type).]]>
+      </doc>
+    </method>
+    <method name="only" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches objects equal to the given object.]]>
+      </doc>
+    </method>
+    <method name="identicalTo" return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.Object"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches only the given object.]]>
+      </doc>
+    </method>
+    <method name="inPackage" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetPackage" type="java.lang.Package"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches classes in the given package. Packages are specific to their
+ classloader, so classes with the same package name may not have the same package at runtime.]]>
+      </doc>
+    </method>
+    <method name="inSubpackage" return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetPackageName" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches classes in the given package and its subpackages. Unlike
+ {@link #inPackage(Package) inPackage()}, this matches classes from any classloader.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="returns" return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.Method&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="returnType" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"/>
+      <doc>
+      <![CDATA[Returns a matcher which matches methods with matching return types.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Matcher implementations. Supports matching classes and methods.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.matcher.Matchers -->
+</package>
+<package name="com.google.inject.multibindings">
+  <!-- start class com.google.inject.multibindings.MapBinder -->
+  <class name="MapBinder" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;"/>
+      <param name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="newMapBinder" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="keyType" type="java.lang.Class&lt;K&gt;"/>
+      <param name="valueType" type="java.lang.Class&lt;V&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a
+ {@link Map} that is itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="permitDuplicates" return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Configures the {@code MapBinder} to handle duplicate entries.
+ <p>When multiple equal keys are bound, the value that gets included in the map is
+ arbitrary.
+ <p>In addition to the {@code Map<K, V>} and {@code Map<K, Provider<V>>}
+ maps that are normally bound, a {@code Map<K, Set<V>>} and
+ {@code Map<K, Set<Provider<V>>>} are <em>also</em> bound, which contain
+ all values bound to each key.
+ <p>
+ When multiple modules contribute elements to the map, this configuration
+ option impacts all of them.
+
+ @return this map binder
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="addBinding" return="com.google.inject.binder.LinkedBindingBuilder&lt;V&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="K"/>
+      <doc>
+      <![CDATA[Returns a binding builder used to add a new entry in the map. Each
+ key must be distinct (and non-null). Bound providers will be evaluated each
+ time the map is injected.
+
+ <p>It is an error to call this method without also calling one of the
+ {@code to} methods on the returned binding builder.
+
+ <p>Scoping elements independently is supported. Use the {@code in} method
+ to specify a binding scope.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An API to bind multiple map entries separately, only to later inject them as
+ a complete map. MapBinder is intended for use in your application's module:
+ <pre><code>
+ public class SnacksModule extends AbstractModule {
+   protected void configure() {
+     MapBinder&lt;String, Snack&gt; mapbinder
+         = MapBinder.newMapBinder(binder(), String.class, Snack.class);
+     mapbinder.addBinding("twix").toInstance(new Twix());
+     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
+     mapbinder.addBinding("skittles").to(Skittles.class);
+   }
+ }</code></pre>
+
+ <p>With this binding, a {@link Map}{@code <String, Snack>} can now be
+ injected:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Map&lt;String, Snack&gt; snacks) { ... }
+ }</code></pre>
+
+ <p>In addition to binding {@code Map<K, V>}, a mapbinder will also bind
+ {@code Map<K, Provider<V>>} for lazy value provision:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Map&lt;String, Provider&lt;Snack&gt;&gt; snackProviders) { ... }
+ }</code></pre>
+
+ <p>Contributing mapbindings from different modules is supported. For example,
+ it is okay to have both {@code CandyModule} and {@code ChipsModule} both
+ create their own {@code MapBinder<String, Snack>}, and to each contribute
+ bindings to the snacks map. When that map is injected, it will contain
+ entries from both modules.
+
+ <p>The map's iteration order is consistent with the binding order. This is
+ convenient when multiple elements are contributed by the same module because
+ that module can order its bindings appropriately. Avoid relying on the
+ iteration order of elements contributed by different modules, since there is
+ no equivalent mechanism to order modules.
+
+ <p>The map is unmodifiable.  Elements can only be added to the map by
+ configuring the MapBinder.  Elements can never be removed from the map.
+
+ <p>Values are resolved at map injection time. If a value is bound to a
+ provider, that provider's get method will be called each time the map is
+ injected (unless the binding is also scoped, or a map of providers is injected).
+
+ <p>Annotations are used to create different maps of the same key/value
+ type. Each distinct annotation gets its own independent map.
+
+ <p><strong>Keys must be distinct.</strong> If the same key is bound more than
+ once, map injection will fail. However, use {@link #permitDuplicates()} in
+ order to allow duplicate keys; extra bindings to {@code Map<K, Set<V>>} and
+ {@code Map<K, Set<Provider<V>>} will be added.
+
+ <p><strong>Keys must be non-null.</strong> {@code addBinding(null)} will
+ throw an unchecked exception.
+
+ <p><strong>Values must be non-null to use map injection.</strong> If any
+ value is null, map injection will fail (although injecting a map of providers
+ will not).
+
+ @author dpb@google.com (David P. Baker)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.multibindings.MapBinder -->
+  <!-- start interface com.google.inject.multibindings.MapBinderBinding -->
+  <interface name="MapBinderBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getMapKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the {@link Key} for the map.]]>
+      </doc>
+    </method>
+    <method name="getKeyTypeLiteral" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the TypeLiteral describing the keys of the map.
+ <p>
+ The TypeLiteral will always match the type Map's generic type. For example, if getMapKey
+ returns a key of <code>Map&lt;String, Snack></code>, then this will always return a
+ <code>TypeLiteral&lt;String></code>.]]>
+      </doc>
+    </method>
+    <method name="getValueTypeLiteral" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the TypeLiteral describing the values of the map.
+ <p>
+ The TypeLiteral will always match the type Map's generic type. For example, if getMapKey
+ returns a key of <code>Map&lt;String, Snack></code>, then this will always return a
+ <code>TypeLiteral&lt;Snack></code>.]]>
+      </doc>
+    </method>
+    <method name="getEntries" return="java.util.List&lt;java.util.Map.Entry&lt;?, com.google.inject.Binding&lt;?&gt;&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all entries in the Map. The returned list of Map.Entries contains the key and a binding
+ to the value. Duplicate keys or values will exist as separate Map.Entries in the returned list.
+ This is only supported on bindings returned from an injector. This will throw
+ {@link UnsupportedOperationException} if it is called on an element retrieved from
+ {@link Elements#getElements}.
+ <p>
+ The elements will always match the type Map's generic type. For example, if getMapKey returns a
+ key of <code>Map&lt;String, Snack></code>, then this will always return a list of type
+ <code>List&lt;Map.Entry&lt;String, Binding&lt;Snack>>></code>.]]>
+      </doc>
+    </method>
+    <method name="permitsDuplicates" return="boolean"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if the MapBinder permits duplicates. This is only supported on bindings returned
+ from an injector. This will throw {@link UnsupportedOperationException} if it is called on a
+ MapBinderBinding retrieved from {@link Elements#getElements}.]]>
+      </doc>
+    </method>
+    <method name="containsElement" return="boolean"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="element" type="com.google.inject.spi.Element"/>
+      <doc>
+      <![CDATA[Returns true if this MapBinder contains the given Element in order to build the map or uses the
+ given Element in order to support building and injecting the map. This will work for
+ MapBinderBindings retrieved from an injector and {@link Elements#getElements}. Usually this is
+ only necessary if you are working with elements retrieved from modules (without an Injector),
+ otherwise {@link #getEntries} and {@link #permitsDuplicates} are better options.
+ <p>
+ If you need to introspect the details of the map, such as the keys, values or if it permits
+ duplicates, it is necessary to pass the elements through an Injector and use
+ {@link #getEntries()} and {@link #permitsDuplicates()}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding for a MapBinder.
+ <p>
+ Although MapBinders may be injected through a variety of generic types (Map&lt;K, V>, Map
+ &lt;K, Provider&lt;V>>, Map&lt;K, Set&lt;V>>, Map<K, Set&lt;
+ Provider&lt;V>>, and even Set&lt;Map.Entry&lt;K, Provider&lt;V>>), a
+ MapBinderBinding exists only on the Binding associated with the Map&lt;K, V> key. Other
+ bindings can be validated to be derived from this MapBinderBinding using
+ {@link #containsElement(Element)}.
+ 
+ @param <T> The fully qualified type of the map, including Map. For example:
+          <code>MapBinderBinding&lt;Map&lt;String, Snack>></code>
+ 
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.multibindings.MapBinderBinding -->
+  <!-- start class com.google.inject.multibindings.Multibinder -->
+  <class name="Multibinder" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with no binding annotation.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotation}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="newSetBinder" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
+ itself bound with {@code annotationType}.]]>
+      </doc>
+    </method>
+    <method name="permitDuplicates" return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Configures the bound set to silently discard duplicate elements. When multiple equal values are
+ bound, the one that gets included is arbitrary. When multiple modules contribute elements to
+ the set, this configuration option impacts all of them.
+
+ @return this multibinder
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="addBinding" return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a binding builder used to add a new element in the set. Each
+ bound element must have a distinct value. Bound providers will be
+ evaluated each time the set is injected.
+
+ <p>It is an error to call this method without also calling one of the
+ {@code to} methods on the returned binding builder.
+
+ <p>Scoping elements independently is supported. Use the {@code in} method
+ to specify a binding scope.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An API to bind multiple values separately, only to later inject them as a
+ complete collection. Multibinder is intended for use in your application's
+ module:
+ <pre><code>
+ public class SnacksModule extends AbstractModule {
+   protected void configure() {
+     Multibinder&lt;Snack&gt; multibinder
+         = Multibinder.newSetBinder(binder(), Snack.class);
+     multibinder.addBinding().toInstance(new Twix());
+     multibinder.addBinding().toProvider(SnickersProvider.class);
+     multibinder.addBinding().to(Skittles.class);
+   }
+ }</code></pre>
+
+ <p>With this binding, a {@link Set}{@code <Snack>} can now be injected:
+ <pre><code>
+ class SnackMachine {
+   {@literal @}Inject
+   public SnackMachine(Set&lt;Snack&gt; snacks) { ... }
+ }</code></pre>
+
+ <p>Contributing multibindings from different modules is supported. For
+ example, it is okay for both {@code CandyModule} and {@code ChipsModule}
+ to create their own {@code Multibinder<Snack>}, and to each contribute
+ bindings to the set of snacks. When that set is injected, it will contain
+ elements from both modules.
+
+ <p>The set's iteration order is consistent with the binding order. This is
+ convenient when multiple elements are contributed by the same module because
+ that module can order its bindings appropriately. Avoid relying on the
+ iteration order of elements contributed by different modules, since there is
+ no equivalent mechanism to order modules.
+
+ <p>The set is unmodifiable.  Elements can only be added to the set by
+ configuring the multibinder.  Elements can never be removed from the set.
+
+ <p>Elements are resolved at set injection time. If an element is bound to a
+ provider, that provider's get method will be called each time the set is
+ injected (unless the binding is also scoped).
+
+ <p>Annotations are be used to create different sets of the same element
+ type. Each distinct annotation gets its own independent collection of
+ elements.
+
+ <p><strong>Elements must be distinct.</strong> If multiple bound elements
+ have the same value, set injection will fail.
+
+ <p><strong>Elements must be non-null.</strong> If any set element is null,
+ set injection will fail.
+
+ @author jessewilson@google.com (Jesse Wilson)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.multibindings.Multibinder -->
+  <!-- start interface com.google.inject.multibindings.MultibinderBinding -->
+  <interface name="MultibinderBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSetKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for the set.]]>
+      </doc>
+    </method>
+    <method name="getElementTypeLiteral" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the TypeLiteral that describes the type of elements in the set.
+ <p>
+ The elements will always match the type Set's generic type. For example, if getSetKey returns a
+ key of <code>Set&lt;String></code>, then this will always return a
+ <code>TypeLiteral&lt;String></code>.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all bindings that make up the set. This is only supported on bindings returned from an
+ injector. This will throw {@link UnsupportedOperationException} if it is called on an element
+ retrieved from {@link Elements#getElements}.
+ <p>
+ The elements will always match the type Set's generic type. For example, if getSetKey returns a
+ key of <code>Set&lt;String></code>, then this will always return a list of type
+ <code>List&lt;Binding&lt;String>></code>.]]>
+      </doc>
+    </method>
+    <method name="permitsDuplicates" return="boolean"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if the multibinder permits duplicates. This is only supported on bindings returned
+ from an injector. This will throw {@link UnsupportedOperationException} if it is called on a
+ MultibinderBinding retrieved from {@link Elements#getElements}.]]>
+      </doc>
+    </method>
+    <method name="containsElement" return="boolean"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="element" type="com.google.inject.spi.Element"/>
+      <doc>
+      <![CDATA[Returns true if this Multibinder uses the given Element. This will be true for bindings that
+ derive the elements of the set and other bindings that Multibinder uses internally. This will
+ work for MultibinderBindings retrieved from an injector and {@link Elements#getElements}.
+ Usually this is only necessary if you are working with elements retrieved from modules (without
+ an Injector), otherwise {@link #getElements} and {@link #permitsDuplicates} are better options.
+ <p>
+ If you need to introspect the details of the set, such as the values or if it permits
+ duplicates, it is necessary to pass the elements through an Injector and use
+ {@link #getElements()} and {@link #permitsDuplicates()}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding for a Multibinder.
+ 
+ @param <T> The fully qualified type of the set, including Set. For example:
+          <code>MultibinderBinding&lt;Set&lt;Boolean>></code>
+ 
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.multibindings.MultibinderBinding -->
+  <!-- start interface com.google.inject.multibindings.MultibindingsTargetVisitor -->
+  <interface name="MultibindingsTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="multibinding" type="com.google.inject.multibindings.MultibinderBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visits a binding created through {@link Multibinder}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="mapbinding" type="com.google.inject.multibindings.MapBinderBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visits a binding created through {@link MapBinder}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A visitor for the multibinder extension.
+ <p>
+ If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ {@link Multibinder} or {@link MapBinder} will be visited through this interface.
+ 
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.multibindings.MultibindingsTargetVisitor -->
+</package>
+<package name="com.google.inject.name">
+  <!-- start class com.google.inject.name.Named -->
+  <class name="Named"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates named things.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.name.Named -->
+  <!-- start class com.google.inject.name.Names -->
+  <class name="Names" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="named" return="com.google.inject.name.Named"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a {@link Named} annotation with {@code name} as the value.]]>
+      </doc>
+    </method>
+    <method name="bindProperties"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="properties" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+      <doc>
+      <![CDATA[Creates a constant binding to {@code @Named(key)} for each entry in
+ {@code properties}.]]>
+      </doc>
+    </method>
+    <method name="bindProperties"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="properties" type="java.util.Properties"/>
+      <doc>
+      <![CDATA[Creates a constant binding to {@code @Named(key)} for each property. This
+ method binds all properties including those inherited from 
+ {@link Properties#defaults defaults}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Utility methods for use with {@code @}{@link Named}.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.name.Names -->
+</package>
+<package name="com.google.inject.persist">
+  <!-- start class com.google.inject.persist.PersistFilter -->
+  <class name="PersistFilter" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="PersistFilter" type="com.google.inject.persist.UnitOfWork, com.google.inject.persist.PersistService"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="init"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterConfig" type="FilterConfig"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="destroy"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="doFilter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletRequest" type="ServletRequest"/>
+      <param name="servletResponse" type="ServletResponse"/>
+      <param name="filterChain" type="FilterChain"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <doc>
+    <![CDATA[Apply this filter to enable the HTTP Request unit of work and to have
+ guice-persist manage the lifecycle of active units of work.
+ The filter automatically starts and stops the relevant {@link PersistService}
+ upon {@link javax.servlet.Filter#init(javax.servlet.FilterConfig)} and
+ {@link javax.servlet.Filter#destroy()} respectively.
+
+ <p> To be able to use the open session-in-view pattern (i.e. work per request),
+ register this filter <b>once</b> in your Guice {@code ServletModule}. It is
+ important that you register this filter before any other filter.
+
+ For multiple providers, you should register this filter once per provider, inside
+ a private module for each persist module installed (this must be the same private
+ module where the specific persist module is itself installed).
+
+ <p>
+ Example configuration:
+ <pre>{@code
+  public class MyModule extends ServletModule {
+    public void configureServlets() {
+      filter("/*").through(PersistFilter.class);
+
+      serve("/index.html").with(MyHtmlServlet.class);
+      // Etc.
+    }
+  }
+ }</pre>
+ <p>
+ This filter is thread safe and allows you to create injectors concurrently
+ and deploy multiple guice-persist modules within the same injector, or even
+ multiple injectors with persist modules withing the same JVM or web app.
+ <p>
+ This filter requires the Guice Servlet extension.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.PersistFilter -->
+  <!-- start class com.google.inject.persist.PersistModule -->
+  <class name="PersistModule" extends="com.google.inject.AbstractModule"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="PersistModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="configurePersistence"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTransactionInterceptor" return="org.aopalliance.intercept.MethodInterceptor"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Install this module to add guice-persist library support for JPA persistence
+ providers.
+
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.PersistModule -->
+  <!-- start interface com.google.inject.persist.PersistService -->
+  <interface name="PersistService"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="start"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Starts the underlying persistence engine and makes guice-persist ready for
+ use. For instance, with JPA, it creates an EntityManagerFactory and may
+ open connection pools. This method must be called by your code prior to
+ using any guice-persist or JPA artifacts. If already started,
+ calling this method does nothing, if already stopped, it also does
+ nothing.]]>
+      </doc>
+    </method>
+    <method name="stop"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Stops the underlying persistence engine. For instance, with JPA, it
+ closes the {@code EntityManagerFactory}. If already stopped, calling this
+ method does nothing. If not yet started, it also does nothing.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Persistence provider service. Use this to manage the overall
+ startup and stop of the persistence module(s).
+
+ TODO(dhanji): Integrate with Service API when appropriate.
+
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.persist.PersistService -->
+  <!-- start class com.google.inject.persist.Transactional -->
+  <class name="Transactional"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[<p> Any method or class marked with this annotation will be considered for transactionality.
+ Consult the documentation on http://code.google.com/p/google-guice for detailed semantics.
+ Marking a method {@code @Transactional} will start a new transaction before the method
+ executes and commit it after the method returns.
+ <p>
+ If the method throws an exception, the transaction will be rolled back <em>unless</em>
+ you have specifically requested not to in the {@link #ignore()} clause.
+ <p>
+ Similarly, the set of exceptions that will trigger a rollback can be defined in
+ the {@link #rollbackOn()} clause. By default, only unchecked exceptions trigger a
+ rollback.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.Transactional -->
+  <!-- start interface com.google.inject.persist.UnitOfWork -->
+  <interface name="UnitOfWork"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="begin"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Starts a Unit Of Work. Underneath, causes a session to the data layer to be opened. If there
+ is already one open, the invocation will do nothing. In this way, you can define arbitrary
+ units-of-work that nest within one another safely.
+
+ Transaction semantics are not affected.]]>
+      </doc>
+    </method>
+    <method name="end"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Declares an end to the current Unit of Work. Underneath, causes any open session to the data
+ layer to close. If there is no Unit of work open, then the call returns silently. You can
+ safely invoke end() repeatedly.
+ <p>
+ Transaction semantics are not affected.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[This interface is used to gain manual control over the unit of work. This is mostly to do
+ work in non-request, non-transactional threads. Or where more fine-grained control over the unit
+ of work is required. Starting and ending a unit of work directly corresponds to opening and
+ closing a {@code Session}, {@code EntityManager} or {@code ObjectContainer} respectively.
+ <p> The
+ Unit of Work referred to by UnitOfWork will always be local to the calling thread. Be careful to
+ end() in a finally block. Neither JPA, nor Hibernate supports threadsafe sessions (reasoning
+ behind thread-locality of Unit of Work semantics).
+
+ <ul>
+   <li>Using UnitOfWork with the PersistFilter inside a request is not recommended.</li>
+   <li>Using UnitOfWork with session-per-txn strategy is not terribly clever either.</li>
+   <li>Using UnitOfWork with session-per-request strategy but *outside* a request (i.e. in a
+       background or bootstrap thread) is probably a good use case.</li>
+  </ul>
+
+ @author Dhanji R. Prasanna (dhanji@gmail com)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.persist.UnitOfWork -->
+</package>
+<package name="com.google.inject.persist.finder">
+  <!-- start class com.google.inject.persist.finder.DynamicFinder -->
+  <class name="DynamicFinder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="DynamicFinder" type="java.lang.reflect.Method"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="from" return="com.google.inject.persist.finder.DynamicFinder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="method" type="java.lang.reflect.Method"/>
+      <doc>
+      <![CDATA[Returns some metadata if the method is annotated {@code @Finder} or null.
+
+ @param method a method you want to test as a dynamic finder]]>
+      </doc>
+    </method>
+    <method name="metadata" return="com.google.inject.persist.finder.Finder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Utility that helps you introspect dynamic finder methods.
+
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.finder.DynamicFinder -->
+  <!-- start class com.google.inject.persist.finder.Finder -->
+  <class name="Finder"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Marks a method stub as a dynamic finder. The method is intercepted and replaced with the
+ specified JPAQL query. Provides result auto-boxing and automatic parameter binding.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.finder.Finder -->
+  <!-- start class com.google.inject.persist.finder.FirstResult -->
+  <class name="FirstResult"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotate any dynamic finder method's integer argument with this to pass in
+ the index of the first result in the result set you are interested in.
+ Useful for paging result sets. Complemented by {@link MaxResults}.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.finder.FirstResult -->
+  <!-- start class com.google.inject.persist.finder.MaxResults -->
+  <class name="MaxResults"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotate any dynamic finder method's integer argument with this to pass in
+ the maximum size of returned result window. Usefule for paging result sets.
+ Complement of {@link FirstResult}.
+
+ @author Dhanji R. Prasanna (dhanji@gmail.com)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.finder.MaxResults -->
+</package>
+<package name="com.google.inject.persist.jpa">
+  <!-- start class com.google.inject.persist.jpa.JpaPersistModule -->
+  <class name="JpaPersistModule" extends="com.google.inject.persist.PersistModule"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="JpaPersistModule" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configurePersistence"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTransactionInterceptor" return="org.aopalliance.intercept.MethodInterceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="properties" return="com.google.inject.persist.jpa.JpaPersistModule"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="properties" type="java.util.Properties"/>
+      <doc>
+      <![CDATA[Configures the JPA persistence provider with a set of properties.
+ 
+ @param properties A set of name value pairs that configure a JPA persistence
+ provider as per the specification.]]>
+      </doc>
+    </method>
+    <method name="addFinder" return="com.google.inject.persist.jpa.JpaPersistModule"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="iface" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Adds an interface to this module to use as a dynamic finder.
+
+ @param iface Any interface type whose methods are all dynamic finders.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[JPA provider for guice persist.
+
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.persist.jpa.JpaPersistModule -->
+</package>
+<package name="com.google.inject.servlet">
+  <!-- start class com.google.inject.servlet.GuiceFilter -->
+  <class name="GuiceFilter" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceFilter"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="doFilter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletRequest" type="ServletRequest"/>
+      <param name="servletResponse" type="ServletResponse"/>
+      <param name="filterChain" type="FilterChain"/>
+      <exception name="IOException" type="java.io.IOException"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="init"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterConfig" type="FilterConfig"/>
+      <exception name="ServletException" type="ServletException"/>
+    </method>
+    <method name="destroy"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[<p>
+ Apply this filter in web.xml above all other filters (typically), to all requests where you plan
+  to use servlet scopes. This is also needed in order to dispatch requests to injectable filters
+  and servlets:
+  <pre>
+  &lt;filter&gt;
+    &lt;filter-name&gt;guiceFilter&lt;/filter-name&gt;
+    &lt;filter-class&gt;<b>com.google.inject.servlet.GuiceFilter</b>&lt;/filter-class&gt;
+  &lt;/filter&gt;
+
+  &lt;filter-mapping&gt;
+    &lt;filter-name&gt;guiceFilter&lt;/filter-name&gt;
+    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+  &lt;/filter-mapping&gt;
+  </pre>
+
+ This filter must appear before every filter that makes use of Guice injection or servlet
+ scopes functionality. Typically, you will only register this filter in web.xml and register
+ any other filters (and servlets) using a {@link ServletModule}.
+
+ @author crazybob@google.com (Bob Lee)
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.GuiceFilter -->
+  <!-- start class com.google.inject.servlet.GuiceServletContextListener -->
+  <class name="GuiceServletContextListener" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="GuiceServletContextListener"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="contextInitialized"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletContextEvent" type="ServletContextEvent"/>
+    </method>
+    <method name="contextDestroyed"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletContextEvent" type="ServletContextEvent"/>
+    </method>
+    <method name="getInjector" return="com.google.inject.Injector"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Override this method to create (or otherwise obtain a reference to) your
+ injector.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[As of Guice 2.0 you can still use (your subclasses of) {@code GuiceServletContextListener}
+ class as a logical place to create and configure your injector. This will ensure the injector
+ is created when the web application is deployed.
+ 
+ @author Kevin Bourrillion (kevinb@google.com)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.GuiceServletContextListener -->
+  <!-- start interface com.google.inject.servlet.InstanceFilterBinding -->
+  <interface name="InstanceFilterBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.servlet.ServletModuleBinding"/>
+    <method name="getFilterInstance" return="Filter"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the filter instance that will be used.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a single instance of a filter. 
+
+ @author sameb@google.com
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.InstanceFilterBinding -->
+  <!-- start interface com.google.inject.servlet.InstanceServletBinding -->
+  <interface name="InstanceServletBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.servlet.ServletModuleBinding"/>
+    <method name="getServletInstance" return="HttpServlet"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the servlet instance that will be used.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a single instance of a servlet. 
+
+ @author sameb@google.com
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.InstanceServletBinding -->
+  <!-- start interface com.google.inject.servlet.LinkedFilterBinding -->
+  <interface name="LinkedFilterBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.servlet.ServletModuleBinding"/>
+    <method name="getLinkedKey" return="com.google.inject.Key&lt;? extends Filter&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key used to lookup the filter instance.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A linked binding to a filter. 
+
+ @author sameb@google.com
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.LinkedFilterBinding -->
+  <!-- start interface com.google.inject.servlet.LinkedServletBinding -->
+  <interface name="LinkedServletBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.servlet.ServletModuleBinding"/>
+    <method name="getLinkedKey" return="com.google.inject.Key&lt;? extends HttpServlet&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key used to lookup the servlet instance.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A linked binding to a servlet. 
+
+ @author sameb@google.com
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.LinkedServletBinding -->
+  <!-- start class com.google.inject.servlet.RequestParameters -->
+  <class name="RequestParameters"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to field or parameters of type {@code Map<String, String[]>}
+ when you want the HTTP request parameter map to be injected.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.RequestParameters -->
+  <!-- start class com.google.inject.servlet.RequestScoped -->
+  <class name="RequestScoped"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want one instance per request.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.RequestScoped -->
+  <!-- start class com.google.inject.servlet.ScopingException -->
+  <class name="ScopingException" extends="java.lang.IllegalStateException"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ScopingException" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <doc>
+    <![CDATA[Exception thrown when there was a failure entering request scope.
+
+ @author Chris Nokleberg]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ScopingException -->
+  <!-- start class com.google.inject.servlet.ScopingOnly -->
+  <class name="ScopingOnly"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates a {@link GuiceFilter} that provides scope functionality, but
+ doesn't dispatch to {@link ServletModule} bound servlets or filters.
+
+ @author iqshum@google.com (Isaac Shum)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ScopingOnly -->
+  <!-- start class com.google.inject.servlet.ServletModule -->
+  <class name="ServletModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ServletModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <method name="configureServlets"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[<h3>Servlet Mapping EDSL</h3>
+
+ <p> Part of the EDSL builder language for configuring servlets
+ and filters with guice-servlet. Think of this as an in-code replacement for web.xml.
+ Filters and servlets are configured here using simple java method calls. Here is a typical
+ example of registering a filter when creating your Guice injector:
+
+ <pre>
+   Guice.createInjector(..., new ServletModule() {
+
+     {@literal @}Override
+     protected void configureServlets() {
+       <b>serve("*.html").with(MyServlet.class)</b>
+     }
+   }
+ </pre>
+
+ This registers a servlet (subclass of {@code HttpServlet}) called {@code MyServlet} to service
+ any web pages ending in {@code .html}. You can also use a path-style syntax to register
+ servlets:
+
+ <pre>
+       <b>serve("/my/*").with(MyServlet.class)</b>
+ </pre>
+
+ Every servlet (or filter) is required to be a singleton. If you cannot annotate the class
+ directly, you should add a separate {@code bind(..).in(Singleton.class)} rule elsewhere in
+ your module. Mapping a servlet that is bound under any other scope is an error.
+
+ <p>
+ <h4>Dispatch Order</h4>
+ You are free to register as many servlets and filters as you like this way. They will
+ be compared and dispatched in the order in which the filter methods are called:
+
+ <pre>
+
+   Guice.createInjector(..., new ServletModule() {
+
+     {@literal @}Override
+     protected void configureServlets() {
+       filter("/*").through(MyFilter.class);
+       filter("*.css").through(MyCssFilter.class);
+       filter("*.jpg").through(new MyJpgFilter());
+       // etc..
+
+       serve("*.html").with(MyServlet.class);
+       serve("/my/*").with(MyServlet.class);
+       serve("*.jpg").with(new MyServlet());
+       // etc..
+      }
+    }
+ </pre>
+ This will traverse down the list of rules in lexical order. For example, a url
+  "{@code /my/file.js}" (after it runs through the matching filters) will first
+  be compared against the servlet mapping:
+ 
+ <pre>
+       serve("*.html").with(MyServlet.class);
+ </pre>
+ And failing that, it will descend to the next servlet mapping:
+
+ <pre>
+       serve("/my/*").with(MyServlet.class);
+ </pre>
+
+ Since this rule matches, Guice Servlet will dispatch to {@code MyServlet}. These
+ two mapping rules can also be written in more compact form using varargs syntax:
+
+ <pre>
+       serve(<b>"*.html", "/my/*"</b>).with(MyServlet.class);
+ </pre>
+ 
+ This way you can map several URI patterns to the same servlet. A similar syntax is
+ also available for filter mappings.
+
+ <p>
+ <h4>Regular Expressions</h4>
+ You can also map servlets (or filters) to URIs using regular expressions:
+ <pre>
+    <b>serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)</b>
+ </pre>
+
+ This will map any URI containing the text "ajax" in it to {@code MyAjaxServlet}. Such as:
+ <ul>
+ <li>http://www.google.com/ajax.html</li>
+ <li>http://www.google.com/content/ajax/index</li>
+ <li>http://www.google.com/it/is_totally_ajaxian</li>
+ </ul>
+
+
+ <h3>Initialization Parameters</h3>
+
+ Servlets (and filters) allow you to pass in init params
+ using the {@code <init-param>} tag in web.xml. You can similarly pass in parameters to
+ Servlets and filters registered in Guice-servlet using a {@link java.util.Map} of parameter
+ name/value pairs. For example, to initialize {@code MyServlet} with two parameters
+ ({@code name="Dhanji", site="google.com"}) you could write:
+
+ <pre>
+  Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
+  params.put("name", "Dhanji");
+  params.put("site", "google.com");
+
+  ...
+      serve("/*").with(MyServlet.class, <b>params</b>)
+ </pre>
+
+ <p>
+ <h3>Binding Keys</h3>
+
+ You can also bind keys rather than classes. This lets you hide
+ implementations with package-local visbility and expose them using
+ only a Guice module and an annotation:
+
+ <pre>
+  ...
+      filter("/*").through(<b>Key.get(Filter.class, Fave.class)</b>);
+ </pre>
+
+ Where {@code Filter.class} refers to the Servlet API interface and {@code Fave.class} is a
+ custom binding annotation. Elsewhere (in one of your own modules) you can bind this
+ filter's implementation:
+
+ <pre>
+   bind(Filter.class)<b>.annotatedWith(Fave.class)</b>.to(MyFilterImpl.class);
+ </pre>
+
+ See {@link com.google.inject.Binder} for more information on binding syntax.
+
+ <p>
+ <h3>Multiple Modules</h3>
+
+ It is sometimes useful to capture servlet and filter mappings from multiple different
+ modules. This is essential if you want to package and offer drop-in Guice plugins that
+ provide servlet functionality.
+
+ <p>
+ Guice Servlet allows you to register several instances of {@code ServletModule} to your
+ injector. The order in which these modules are installed determines the dispatch order
+ of filters and the precedence order of servlets. For example, if you had two servlet modules,
+ {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped
+ to the same URI pattern, {@code "/*"}:
+
+ <p>
+ In {@code RpcModule}:
+ <pre>
+     filter("/*").through(RpcFilter.class);
+ </pre>
+
+ In {@code WebServiceModule}:
+ <pre>
+     filter("/*").through(WebServiceFilter.class);
+ </pre>
+
+ Then the order in which these filters are dispatched is determined by the order in which
+ the modules are installed:
+
+ <pre>
+   <b>install(new WebServiceModule());</b>
+   install(new RpcModule());
+ </pre>
+
+ In the case shown above {@code WebServiceFilter} will run first.
+ 
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="filter" return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="urlPattern" type="java.lang.String"/>
+      <param name="morePatterns" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="filterRegex" return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="regex" type="java.lang.String"/>
+      <param name="regexes" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param regex Any Java-style regular expression.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="serve" return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="urlPattern" type="java.lang.String"/>
+      <param name="morePatterns" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="serveRegex" return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <param name="regex" type="java.lang.String"/>
+      <param name="regexes" type="java.lang.String[]"/>
+      <doc>
+      <![CDATA[@param regex Any Java-style regular expression.
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="getServletContext" return="ServletContext"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="true" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[This method only works if you are using the {@linkplain GuiceServletContextListener} to
+ create your injector. Otherwise, it returns null.
+ @return The current servlet context.
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Configures the servlet scopes and creates bindings for the servlet API
+ objects so you can inject the request, response, session, etc.
+
+ <p>
+ You should subclass this module to register servlets and
+ filters in the {@link #configureServlets()} method.
+
+ @author crazybob@google.com (Bob Lee)
+ @author dhanji@gmail.com (Dhanji R. Prasanna)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ServletModule -->
+  <!-- start interface com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder -->
+  <interface name="ServletModule.FilterKeyBindingBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="through"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;"/>
+    </method>
+    <method name="through"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;"/>
+    </method>
+    <method name="through"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filter" type="Filter"/>
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </method>
+    <method name="through"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="through"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="through"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="filter" type="Filter"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link ServletModule#configureServlets()}
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder -->
+  <!-- start interface com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder -->
+  <interface name="ServletModule.ServletKeyBindingBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="with"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;"/>
+    </method>
+    <method name="with"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;"/>
+    </method>
+    <method name="with"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servlet" type="HttpServlet"/>
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </method>
+    <method name="with"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="with"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+    </method>
+    <method name="with"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="servlet" type="HttpServlet"/>
+      <param name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;"/>
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL examples at {@link ServletModule#configureServlets()}
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder -->
+  <!-- start interface com.google.inject.servlet.ServletModuleBinding -->
+  <interface name="ServletModuleBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getUriPatternType" return="com.google.inject.servlet.UriPatternType"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the pattern type that this binding was created with.]]>
+      </doc>
+    </method>
+    <method name="getPattern" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the pattern used to match against the binding.]]>
+      </doc>
+    </method>
+    <method name="getInitParams" return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns any context params supplied when creating the binding.]]>
+      </doc>
+    </method>
+    <method name="matchesUri" return="boolean"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="uri" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Returns true if the given URI will match this binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding created by {@link ServletModule}.
+ 
+ @author sameb@google.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModuleBinding -->
+  <!-- start interface com.google.inject.servlet.ServletModuleTargetVisitor -->
+  <interface name="ServletModuleTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.servlet.LinkedFilterBinding"/>
+      <doc>
+      <![CDATA[Visits a filter binding created by {@link ServletModule#filter}, where
+ {@link FilterKeyBindingBuilder#through} is called with a Class or Key.
+ 
+ If multiple patterns were specified, this will be called multiple times.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.servlet.InstanceFilterBinding"/>
+      <doc>
+      <![CDATA[Visits a filter binding created by {@link ServletModule#filter} where
+ {@link FilterKeyBindingBuilder#through} is called with a {@link Filter}.
+ 
+ If multiple patterns were specified, this will be called multiple times.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.servlet.LinkedServletBinding"/>
+      <doc>
+      <![CDATA[Visits a servlet binding created by {@link ServletModule#serve} where
+ {@link ServletKeyBindingBuilder#with}, is called with a Class or Key.
+ 
+ If multiple patterns were specified, this will be called multiple times.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.servlet.InstanceServletBinding"/>
+      <doc>
+      <![CDATA[Visits a servlet binding created by {@link ServletModule#serve} where 
+ {@link ServletKeyBindingBuilder#with}, is called with an {@link HttpServlet}.
+ 
+ If multiple patterns were specified, this will be called multiple times.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A visitor for the servlet extension.
+ 
+ If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ {@link ServletModule} will be visited through this interface.
+ 
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.servlet.ServletModuleTargetVisitor -->
+  <!-- start class com.google.inject.servlet.ServletScopes -->
+  <class name="ServletScopes" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="continueRequest" return="java.util.concurrent.Callable&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="callable" type="java.util.concurrent.Callable&lt;T&gt;"/>
+      <param name="seedMap" type="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, java.lang.Object&gt;"/>
+      <doc>
+      <![CDATA[Wraps the given callable in a contextual callable that "continues" the
+ HTTP request in another thread. This acts as a way of transporting
+ request context data from the request processing thread to to worker
+ threads.
+ <p>
+ There are some limitations:
+ <ul>
+   <li>Derived objects (i.e. anything marked @RequestScoped will not be
+      transported.</li>
+   <li>State changes to the HttpServletRequest after this method is called
+      will not be seen in the continued thread.</li>
+   <li>Only the HttpServletRequest, ServletContext and request parameter
+      map are available in the continued thread. The response and session
+      are not available.</li>
+ </ul>
+
+ <p>The returned callable will throw a {@link ScopingException} when called
+ if the HTTP request scope is still active on the current thread.
+
+ @param callable code to be executed in another thread, which depends on
+     the request scope.
+ @param seedMap the initial set of scoped instances for Guice to seed the
+     request scope with.  To seed a key with null, use {@code null} as
+     the value.
+ @return a callable that will invoke the given callable, making the request
+     context available to it.
+ @throws OutOfScopeException if this method is called from a non-request
+     thread, or if the request has completed.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="transferRequest" return="java.util.concurrent.Callable&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="callable" type="java.util.concurrent.Callable&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Wraps the given callable in a contextual callable that "transfers" the
+ request to another thread. This acts as a way of transporting
+ request context data from the current thread to a future thread.
+
+ <p>As opposed to {@link #continueRequest}, this method propagates all
+ existing scoped objects. The primary use case is in server implementations
+ where you can detach the request processing thread while waiting for data,
+ and reattach to a different thread to finish processing at a later time.
+
+ <p>Because {@code HttpServletRequest} objects are not typically
+ thread-safe, the callable returned by this method must not be run on a
+ different thread until the current request scope has terminated. In other
+ words, do not use this method to propagate the current request scope to
+ worker threads that may run concurrently with the current thread.
+
+ <p>The returned callable will throw a {@link ScopingException} when called
+ if the request scope being transferred is still active on a different
+ thread.
+
+ @param callable code to be executed in another thread, which depends on
+     the request scope.
+ @return a callable that will invoke the given callable, making the request
+     context available to it.
+ @throws OutOfScopeException if this method is called from a non-request
+     thread, or if the request has completed.]]>
+      </doc>
+    </method>
+    <method name="isRequestScoped" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns true if {@code binding} is request-scoped. If the binding is a
+ {@link com.google.inject.spi.LinkedKeyBinding linked key binding} and
+ belongs to an injector (i. e. it was retrieved via
+ {@link Injector#getBinding Injector.getBinding()}), then this method will
+ also return true if the target binding is request-scoped.]]>
+      </doc>
+    </method>
+    <method name="scopeRequest" return="java.util.concurrent.Callable&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="callable" type="java.util.concurrent.Callable&lt;T&gt;"/>
+      <param name="seedMap" type="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, java.lang.Object&gt;"/>
+      <doc>
+      <![CDATA[Scopes the given callable inside a request scope. This is not the same
+ as the HTTP request scope, but is used if no HTTP request scope is in
+ progress. In this way, keys can be scoped as @RequestScoped and exist
+ in non-HTTP requests (for example: RPC requests) as well as in HTTP
+ request threads.
+
+ <p>The returned callable will throw a {@link ScopingException} when called
+ if there is a request scope already active on the current thread.
+
+ @param callable code to be executed which depends on the request scope.
+     Typically in another thread, but not necessarily so.
+ @param seedMap the initial set of scoped instances for Guice to seed the
+     request scope with.  To seed a key with null, use {@code null} as
+     the value.
+ @return a callable that when called will run inside the a request scope
+     that exposes the instances in the {@code seedMap} as scoped keys.
+ @since 3.0]]>
+      </doc>
+    </method>
+    <field name="REQUEST" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[HTTP servlet request scope.]]>
+      </doc>
+    </field>
+    <field name="SESSION" type="com.google.inject.Scope"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[HTTP session scope.]]>
+      </doc>
+    </field>
+    <doc>
+    <![CDATA[Servlet scopes.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.ServletScopes -->
+  <!-- start class com.google.inject.servlet.SessionScoped -->
+  <class name="SessionScoped"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Apply this to implementation classes when you want one instance per session.
+
+ @see com.google.inject.Scopes#SINGLETON
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.SessionScoped -->
+  <!-- start class com.google.inject.servlet.UriPatternType -->
+  <class name="UriPatternType" extends="java.lang.Enum&lt;com.google.inject.servlet.UriPatternType&gt;"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="values" return="com.google.inject.servlet.UriPatternType[]"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="valueOf" return="com.google.inject.servlet.UriPatternType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+    </method>
+    <doc>
+    <![CDATA[An enumeration of the available URI-pattern matching styles
+ 
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.servlet.UriPatternType -->
+</package>
+<package name="com.google.inject.spi">
+  <!-- start interface com.google.inject.spi.BindingScopingVisitor -->
+  <interface name="BindingScopingVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visitEagerSingleton" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Visit an eager singleton or single instance. This scope strategy is found on both module and
+ injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visitScope" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+      <doc>
+      <![CDATA[Visit a scope instance. This scope strategy is found on both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visitScopeAnnotation" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+      <doc>
+      <![CDATA[Visit a scope annotation. This scope strategy is found only on module bindings. The instance
+ that implements this scope is registered by {@link com.google.inject.Binder#bindScope(Class,
+ Scope) Binder.bindScope()}.]]>
+      </doc>
+    </method>
+    <method name="visitNoScoping" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Visit an unspecified or unscoped strategy. On a module, this strategy indicates that the
+ injector should use scoping annotations to find a scope. On an injector, it indicates that
+ no scope is applied to the binding. An unscoped binding will behave like a scoped one when it
+ is linked to a scoped binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visits each of the strategies used to scope an injection.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.BindingScopingVisitor -->
+  <!-- start interface com.google.inject.spi.BindingTargetVisitor -->
+  <interface name="BindingTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a instance binding. The same instance is returned for every injection. This target is
+ found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a provider instance binding. The provider's {@code get} method is invoked to resolve
+ injections. This target is found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a provider key binding. To resolve injections, the provider key is first resolved, then
+ that provider's {@code get} method is invoked. This target is found in both module and injector
+ bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a linked key binding. The other key's binding is used to resolve injections. This
+ target is found in both module and injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding to a key exposed from an enclosed private environment. This target is only
+ found in injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit an untargetted binding. This target is found only on module bindings. It indicates
+ that the injector should use its implicit binding strategies to resolve injections.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a constructor binding. To resolve injections, an instance is instantiated by invoking
+ {@code constructor}. This target is found only on injector bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding created from converting a bound instance to a new type. The source binding
+ has the same binding annotation but a different type. This target is found only on injector
+ bindings.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visit a binding to a {@link com.google.inject.Provider} that delegates to the binding for the
+ provided type. This target is found only on injector bindings.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visits each of the strategies used to find an instance to satisfy an injection.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.BindingTargetVisitor -->
+  <!-- start interface com.google.inject.spi.ConstructorBinding -->
+  <interface name="ConstructorBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getConstructor" return="com.google.inject.spi.InjectionPoint"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the constructor this binding injects.]]>
+      </doc>
+    </method>
+    <method name="getInjectableMembers" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.]]>
+      </doc>
+    </method>
+    <method name="getMethodInterceptors" return="java.util.Map&lt;java.lang.reflect.Method, java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the interceptors applied to each method, in the order that they will be applied.
+
+ @return a possibly empty map]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to the constructor of a concrete clss. To resolve injections, an instance is
+ instantiated by invoking the constructor.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ConstructorBinding -->
+  <!-- start interface com.google.inject.spi.ConvertedConstantBinding -->
+  <interface name="ConvertedConstantBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getValue" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the converted value.]]>
+      </doc>
+    </method>
+    <method name="getTypeConverterBinding" return="com.google.inject.spi.TypeConverterBinding"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the type converter binding used to convert the constant.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="getSourceKey" return="com.google.inject.Key&lt;java.lang.String&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key for the source binding. That binding can be retrieved from an injector using
+ {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.]]>
+      </doc>
+    </method>
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a singleton set containing only the converted key.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding created from converting a bound instance to a new type. The source binding has the same
+ binding annotation but a different type.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ConvertedConstantBinding -->
+  <!-- start class com.google.inject.spi.DefaultBindingScopingVisitor -->
+  <class name="DefaultBindingScopingVisitor" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;"/>
+    <constructor name="DefaultBindingScopingVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visitEagerSingleton" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="visitScope" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scope" type="com.google.inject.Scope"/>
+    </method>
+    <method name="visitScopeAnnotation" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+    </method>
+    <method name="visitNoScoping" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to
+ {@link #visitOther()}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ 
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultBindingScopingVisitor -->
+  <!-- start class com.google.inject.spi.DefaultBindingTargetVisitor -->
+  <class name="DefaultBindingTargetVisitor" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <constructor name="DefaultBindingTargetVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instanceBinding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerInstanceBinding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerKeyBinding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="linkedKeyBinding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="exposedBinding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="untargettedBinding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructorBinding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="convertedConstantBinding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerBinding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to {@link
+ #visitOther(Binding)}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultBindingTargetVisitor -->
+  <!-- start class com.google.inject.spi.DefaultElementVisitor -->
+  <class name="DefaultElementVisitor" extends="java.lang.Object"
+    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.ElementVisitor&lt;V&gt;"/>
+    <constructor name="DefaultElementVisitor"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="visitOther" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+      <param name="element" type="com.google.inject.spi.Element"/>
+      <doc>
+      <![CDATA[Default visit implementation. Returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorBinding" type="com.google.inject.spi.InterceptorBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="scopeBinding" type="com.google.inject.spi.ScopeBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeConverterBinding" type="com.google.inject.spi.TypeConverterBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providerLookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectionRequest" type="com.google.inject.spi.InjectionRequest&lt;?&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="staticInjectionRequest" type="com.google.inject.spi.StaticInjectionRequest"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="privateElements" type="com.google.inject.spi.PrivateElements"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeListenerBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProvisionListenerBinding"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.DisableCircularProxiesOption"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.RequireExplicitBindingsOption"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.RequireAtInjectOnConstructorsOption"/>
+    </method>
+    <method name="visit" return="V"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.RequireExactBindingAnnotationsOption"/>
+    </method>
+    <doc>
+    <![CDATA[No-op visitor for subclassing. All interface methods simply delegate to
+ {@link #visitOther(Element)}, returning its result.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+
+ @author sberlin@gmail.com (Sam Berlin)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DefaultElementVisitor -->
+  <!-- start class com.google.inject.spi.Dependency -->
+  <class name="Dependency" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="get" return="com.google.inject.spi.Dependency&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new dependency that is not attached to an injection point. The returned dependency is
+ nullable.]]>
+      </doc>
+    </method>
+    <method name="forInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectionPoints" type="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"/>
+      <doc>
+      <![CDATA[Returns the dependencies from the given injection points.]]>
+      </doc>
+    </method>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key to the binding that satisfies this dependency.]]>
+      </doc>
+    </method>
+    <method name="isNullable" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if null is a legal value for this dependency.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoint" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the injection point to which this dependency belongs, or null if this dependency isn't
+ attached to a particular injection point.]]>
+      </doc>
+    </method>
+    <method name="getParameterIndex" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the index of this dependency in the injection point's parameter list, or {@code -1} if
+ this dependency does not belong to a parameter list. Only method and constuctor dependencies
+ are elements in a parameter list.]]>
+      </doc>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[A variable that can be resolved by an injector.
+
+ <p>Use {@link #get} to build a freestanding dependency, or {@link InjectionPoint} to build one
+ that's attached to a constructor, method or field.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Dependency -->
+  <!-- start class com.google.inject.spi.DependencyAndSource -->
+  <class name="DependencyAndSource" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="DependencyAndSource" type="com.google.inject.spi.Dependency&lt;?&gt;, java.lang.Object"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getDependency" return="com.google.inject.spi.Dependency&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the Dependency, if one exists. For anything that can be referenced
+ by {@link Injector#getBinding}, a dependency exists. A dependency will not
+ exist (and this will return null) for types initialized with
+ {@link Binder#requestInjection} or {@link Injector#injectMembers(Object)},
+ nor will it exist for objects injected into Providers bound with
+ LinkedBindingBuilder#toProvider(Provider).]]>
+      </doc>
+    </method>
+    <method name="getBindingSource" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a string describing where this dependency was bound. If the binding
+ was just-in-time, there is no valid binding source, so this describes the
+ class in question.]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[A combination of a {@link Dependency} and the {@link Binding#getSource()
+ source} where the dependency was bound.
+ 
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DependencyAndSource -->
+  <!-- start class com.google.inject.spi.DisableCircularProxiesOption -->
+  <class name="DisableCircularProxiesOption" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to disable circular proxies.
+
+ @author sameb@google.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.DisableCircularProxiesOption -->
+  <!-- start interface com.google.inject.spi.Element -->
+  <interface name="Element"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSource" return="java.lang.Object"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns an arbitrary object containing information about the "place" where this element was
+ configured. Used by Guice in the production of descriptive error messages.
+
+ <p>Tools might specially handle types they know about; {@code StackTraceElement} is a good
+ example. Tools should simply call {@code toString()} on the source object if the type is
+ unfamiliar.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Accepts an element visitor. Invokes the visitor method specific to this element's type.
+
+ @param visitor to call back on]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Writes this module element to the given binder (optional operation).
+
+ @param binder to apply configuration element to
+ @throws UnsupportedOperationException if the {@code applyTo} method is not supported by this
+     element.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A core component of a module or injector.
+
+ <p>The elements of a module can be inspected, validated and rewritten. Use {@link
+ Elements#getElements(com.google.inject.Module[]) Elements.getElements()} to read the elements
+ from a module, and {@link Elements#getModule(Iterable) Elements.getModule()} to rewrite them.
+ This can be used for static analysis and generation of Guice modules.
+
+ <p>The elements of an injector can be inspected and exercised. Use {@link
+ com.google.inject.Injector#getBindings Injector.getBindings()} to reflect on Guice injectors.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.Element -->
+  <!-- start class com.google.inject.spi.Elements -->
+  <class name="Elements" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Elements"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="stage" type="com.google.inject.Stage"/>
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Records the elements executed by {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="getModule" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elements" type="java.lang.Iterable&lt;? extends com.google.inject.spi.Element&gt;"/>
+      <doc>
+      <![CDATA[Returns the module composed of {@code elements}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Exposes elements of a module so they can be inspected, validated or {@link
+ Element#applyTo(Binder) rewritten}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Elements -->
+  <!-- start class com.google.inject.spi.ElementSource -->
+  <class name="ElementSource" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="getOriginalElementSource" return="com.google.inject.spi.ElementSource"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the {@link ElementSource} of the element this was created or copied from. If this was
+ not created or copied from another element, returns {@code null}.]]>
+      </doc>
+    </method>
+    <method name="getDeclaringSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns a single location in source code that defines the element. It can be any object
+ such as {@link Constructor}, {@link Method}, {@link Field}, {@link StackTraceElement}, etc. For
+ example, if the element is created from a method annotated by {@literal @Provides}, the 
+ declaring source of element would be the method itself.]]>
+      </doc>
+    </method>
+    <method name="getModuleClassNames" return="java.util.List&lt;java.lang.String&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the class names of modules involved in creating this {@link Element}. The first
+ element (index 0) is the class name of module that defined the element, and the last element
+ is the class name of root module.]]>
+      </doc>
+    </method>
+    <method name="getModuleConfigurePositionsInStackTrace" return="java.util.List&lt;java.lang.Integer&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the position of {@link Module#configure(Binder) configure(Binder)} method call in the
+ {@link #getStackTrace() stack trace} for modules that their classes returned by
+ {@link #getModuleClassNames()}. For example, if the stack trace looks like the following:
+ <p>
+ {@code
+  0 - Binder.bind(),
+  1 - ModuleTwo.configure(),
+  2 - Binder.install(),
+  3 - ModuleOne.configure(),
+  4 - theRest(). 
+ }
+ <p>
+ 1 and 3 are returned.
+ <p>
+ In the cases where stack trace is not available (i.e., the stack trace was not collected),
+ it returns -1 for all module positions.]]>
+      </doc>
+    </method>
+    <method name="getStackTrace" return="java.lang.StackTraceElement[]"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the sequence of method calls that ends at one of {@link Binder} {@code bindXXX()} 
+ methods and eventually defines the element. Note that {@link #getStackTrace()} lists {@link 
+ StackTraceElement StackTraceElements} in reverse chronological order. The first element (index 
+ zero) is the last method call and the last element is the first method invocation. In the cases
+ where stack trace is not available (i.e.,the stack trace was not collected), it returns an 
+ empty array.]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns {@code getDeclaringSource().toString()} value.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Contains information about where and how an {@link Element element} was bound.
+ <p> 
+ The {@link #getDeclaringSource() declaring source} refers to a location in source code that 
+ defines the Guice {@link Element element}. For example, if the element is created from a method
+ annotated by {@literal @Provides}, the declaring source of element would be the method itself. 
+ <p>
+ The {@link #getStackTrace()} refers to the sequence of calls ends at one of {@link Binder} 
+ {@code bindXXX()} methods and eventually defines the element. Note that {@link #getStackTrace()} 
+ lists {@link StackTraceElement StackTraceElements} in reverse chronological order. The first 
+ element (index zero) is the last method call and the last element is the first method invocation.
+ By default, the stack trace is not collected. The default behavior can be changed by setting the 
+ {@code guice_include_stack_traces} flag value. The value can be either {@code OFF}, {@code
+ ONLY_FOR_DECLARING_SOURCE} or {@code COMPLETE}. Note that collecting stack traces for every
+ binding can cause a performance hit when the injector is created.
+ <p>
+ The sequence of class names of {@link Module modules} involved in the element creation can be 
+ retrieved by {@link #getModuleClassNames()}. Similar to {@link #getStackTrace()}, the order is 
+ reverse chronological. The first module (index 0) is the module that installs the {@link Element 
+ element}. The last module is the root module.
+ <p>
+ In order to support the cases where a Guice {@link Element element} is created from another
+ Guice {@link Element element} (original) (e.g., by {@link Element#applyTo()}), it also
+ provides a reference to the original element source ({@link #getOriginalElementSource()}).]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ElementSource -->
+  <!-- start interface com.google.inject.spi.ElementVisitor -->
+  <interface name="ElementVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.Binding&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a mapping from a key (type and optional annotation) to the strategy for getting
+ instances of the type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.InterceptorBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of interceptors for matching methods of matching classes.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ScopeBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of a scope annotation with the scope that implements it.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeConverterBinding"/>
+      <doc>
+      <![CDATA[Visit a registration of type converters for matching target types.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="request" type="com.google.inject.spi.InjectionRequest&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Visit a request to inject the instance fields and methods of an instance.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="request" type="com.google.inject.spi.StaticInjectionRequest"/>
+      <doc>
+      <![CDATA[Visit a request to inject the static fields and methods of type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a lookup of the provider for a type.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Visit a lookup of the members injector.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Visit an error message and the context in which it occured.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elements" type="com.google.inject.spi.PrivateElements"/>
+      <doc>
+      <![CDATA[Visit a collection of configuration elements for a {@linkplain com.google.inject.PrivateBinder
+ private binder}.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.TypeListenerBinding"/>
+      <doc>
+      <![CDATA[Visit an injectable type listener binding.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binding" type="com.google.inject.spi.ProvisionListenerBinding"/>
+      <doc>
+      <![CDATA[Visit a provision listener binding.]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.RequireExplicitBindingsOption"/>
+      <doc>
+      <![CDATA[Visit a require explicit bindings command.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.DisableCircularProxiesOption"/>
+      <doc>
+      <![CDATA[Visit a disable circular proxies command.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.RequireAtInjectOnConstructorsOption"/>
+      <doc>
+      <![CDATA[Visit a require explicit {@literal @}{@link Inject} command.
+ 
+ @since 4.0]]>
+      </doc>
+    </method>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="option" type="com.google.inject.spi.RequireExactBindingAnnotationsOption"/>
+      <doc>
+      <![CDATA[Visit a require exact binding annotations command.
+
+ @since 4.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Visit elements.
+
+ @param <V> any type to be returned by the visit method. Use {@link Void} with
+     {@code return null} if no return type is needed.
+ 
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ElementVisitor -->
+  <!-- start interface com.google.inject.spi.ExposedBinding -->
+  <interface name="ExposedBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getPrivateElements" return="com.google.inject.spi.PrivateElements"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the enclosed environment that holds the original binding.]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[Unsupported. Always throws {@link UnsupportedOperationException}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a key exposed from an enclosed private environment.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ExposedBinding -->
+  <!-- start interface com.google.inject.spi.HasDependencies -->
+  <interface name="HasDependencies"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getDependencies" return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the known dependencies for this type. If this has dependencies whose values are not
+ known statically, a dependency for the {@link com.google.inject.Injector Injector} will be
+ included in the returned set.
+ 
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Implemented by {@link com.google.inject.Binding bindings}, {@link com.google.inject.Provider
+ providers} and instances that expose their dependencies explicitly.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.HasDependencies -->
+  <!-- start interface com.google.inject.spi.InjectionListener -->
+  <interface name="InjectionListener"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="afterInjection"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="injectee" type="I"/>
+      <doc>
+      <![CDATA[Invoked by Guice after it injects the fields and methods of instance.
+
+ @param injectee instance that Guice injected dependencies into]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Listens for injections into instances of type {@code I}. Useful for performing further
+ injections, post-injection initialization, and more.
+
+ @author crazybob@google.com (Bob Lee)
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.InjectionListener -->
+  <!-- start class com.google.inject.spi.InjectionPoint -->
+  <class name="InjectionPoint" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="getMember" return="java.lang.reflect.Member"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the injected constructor, field, or method.]]>
+      </doc>
+    </method>
+    <method name="getDependencies" return="java.util.List&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the dependencies for this injection point. If the injection point is for a method or
+ constructor, the dependencies will correspond to that member's parameters. Field injection
+ points always have a single dependency for the field itself.
+
+ @return a possibly-empty list]]>
+      </doc>
+    </method>
+    <method name="isOptional" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if this injection point shall be skipped if the injector cannot resolve bindings
+ for all required dependencies. Both explicit bindings (as specified in a module), and implicit
+ bindings ({@literal @}{@link com.google.inject.ImplementedBy ImplementedBy}, default
+ constructors etc.) may be used to satisfy optional injection points.]]>
+      </doc>
+    </method>
+    <method name="isToolable" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns true if the element is annotated with {@literal @}{@link Toolable}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="getDeclaringType" return="com.google.inject.TypeLiteral&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the generic type that defines this injection point. If the member exists on a
+ parameterized type, the result will include more type information than the member's {@link
+ Member#getDeclaringClass() raw declaring class}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="forConstructor" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructor" type="java.lang.reflect.Constructor&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the specified constructor. If the declaring type of {@code
+ constructor} is parameterized (such as {@code List<T>}), prefer the overload that includes a
+ type literal.
+
+ @param constructor any single constructor present on {@code type}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="forConstructor" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="constructor" type="java.lang.reflect.Constructor&lt;T&gt;"/>
+      <param name="type" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the specified constructor of {@code type}.
+
+ @param constructor any single constructor present on {@code type}.
+ @param type the concrete type that defines {@code constructor}.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="forConstructorOf" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the injectable constructor of {@code type}.
+
+ @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
+     or a no-arguments constructor that is not private.
+ @throws ConfigurationException if there is no injectable constructor, more than one injectable
+     constructor, or if parameters of the injectable constructor are malformed, such as a
+     parameter with multiple binding annotations.]]>
+      </doc>
+    </method>
+    <method name="forConstructorOf" return="com.google.inject.spi.InjectionPoint"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns a new injection point for the injectable constructor of {@code type}.
+
+ @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
+     or a no-arguments constructor that is not private.
+ @throws ConfigurationException if there is no injectable constructor, more than one injectable
+     constructor, or if parameters of the injectable constructor are malformed, such as a
+     parameter with multiple binding annotations.]]>
+      </doc>
+    </method>
+    <method name="forStaticMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all static method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forStaticMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all static method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forInstanceMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="forInstanceMethodsAndFields" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns all instance method and field injection points on {@code type}.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A constructor, field or method that can receive injections. Typically this is a member with the
+ {@literal @}{@link Inject} annotation. For non-private, no argument constructors, the member may
+ omit the annotation.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InjectionPoint -->
+  <!-- start class com.google.inject.spi.InjectionRequest -->
+  <class name="InjectionRequest" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="InjectionRequest" type="java.lang.Object, com.google.inject.TypeLiteral&lt;T&gt;, T"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInstance" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="ConfigurationException" type="com.google.inject.ConfigurationException"/>
+      <doc>
+      <![CDATA[Returns the instance methods and fields of {@code instance} that will be injected to fulfill
+ this request.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on the class of {@code
+      instance}, such as a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="R"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;R&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[A request to inject the instance fields and methods of an instance. Requests are created
+ explicitly in a module using {@link com.google.inject.Binder#requestInjection(Object)
+ requestInjection()} statements:
+ <pre>
+     requestInjection(serviceInstance);</pre>
+
+ @author mikeward@google.com (Mike Ward)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InjectionRequest -->
+  <!-- start interface com.google.inject.spi.InstanceBinding -->
+  <interface name="InstanceBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getInstance" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the user-supplied instance.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the field and method injection points of the instance, injected at injector-creation
+ time only.
+
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a single instance. The same instance is returned for every injection.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.InstanceBinding -->
+  <!-- start class com.google.inject.spi.InterceptorBinding -->
+  <class name="InterceptorBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassMatcher" return="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getMethodMatcher" return="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInterceptors" return="java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Registration of interceptors for matching methods of matching classes. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#bindInterceptor(
+ Matcher, Matcher, MethodInterceptor[]) bindInterceptor()} statements:
+ <pre>
+     bindInterceptor(Matchers.subclassesOf(MyAction.class),
+         Matchers.annotatedWith(Transactional.class),
+         new MyTransactionInterceptor());</pre>
+
+ or from an injectable type listener using {@link TypeEncounter#bindInterceptor(Matcher,
+ org.aopalliance.intercept.MethodInterceptor[]) TypeEncounter.bindInterceptor()}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.InterceptorBinding -->
+  <!-- start interface com.google.inject.spi.LinkedKeyBinding -->
+  <interface name="LinkedKeyBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getLinkedKey" return="com.google.inject.Key&lt;? extends T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the linked key used to resolve injections. That binding can be retrieved from an
+ injector using {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a linked key. The other key's binding is used to resolve injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.LinkedKeyBinding -->
+  <!-- start class com.google.inject.spi.MembersInjectorLookup -->
+  <class name="MembersInjectorLookup" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="MembersInjectorLookup" type="java.lang.Object, com.google.inject.TypeLiteral&lt;T&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="com.google.inject.TypeLiteral&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the type containing the members to be injected.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="initializeDelegate"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="delegate" type="com.google.inject.MembersInjector&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Sets the actual members injector.
+
+ @throws IllegalStateException if the delegate is already set]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="getDelegate" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the delegate members injector, or {@code null} if it has not yet been initialized.
+ The delegate will be initialized when this element is processed, or otherwise used to create
+ an injector.]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the looked up members injector. The result is not valid until this lookup has been
+ initialized, which usually happens when the injector is created. The members injector will
+ throw an {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A lookup of the members injector for a type. Lookups are created explicitly in a module using
+ {@link com.google.inject.Binder#getMembersInjector(Class) getMembersInjector()} statements:
+ <pre>
+     MembersInjector&lt;PaymentService&gt; membersInjector
+         = getMembersInjector(PaymentService.class);</pre>
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.MembersInjectorLookup -->
+  <!-- start class com.google.inject.spi.Message -->
+  <class name="Message" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.io.Serializable"/>
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="Message" type="java.util.List&lt;java.lang.Object&gt;, java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </constructor>
+    <constructor name="Message" type="java.lang.String, java.lang.Throwable"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 4.0]]>
+      </doc>
+    </constructor>
+    <constructor name="Message" type="java.lang.Object, java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <constructor name="Message" type="java.lang.String"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getSources" return="java.util.List&lt;java.lang.Object&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <method name="getMessage" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the error message text.]]>
+      </doc>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <method name="getCause" return="java.lang.Throwable"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the throwable that caused this message, or {@code null} if this
+ message was not caused by a throwable.
+
+ @since 2.0]]>
+      </doc>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="hashCode" return="int"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="equals" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="o" type="java.lang.Object"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <doc>
+      <![CDATA[@since 2.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An error message and the context in which it occured. Messages are usually created internally by
+ Guice and its extensions. Messages can be created explicitly in a module using {@link
+ com.google.inject.Binder#addError(Throwable) addError()} statements:
+ <pre>
+     try {
+       bindPropertiesFromFile();
+     } catch (IOException e) {
+       addError(e);
+     }</pre>
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Message -->
+  <!-- start interface com.google.inject.spi.PrivateElements -->
+  <interface name="PrivateElements"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getElements" return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the configuration information in this private environment.]]>
+      </doc>
+    </method>
+    <method name="getInjector" return="com.google.inject.Injector"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the child injector that hosts these private elements, or null if the elements haven't
+ been used to create an injector.]]>
+      </doc>
+    </method>
+    <method name="getExposedKeys" return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the unique exposed keys for these private elements.]]>
+      </doc>
+    </method>
+    <method name="getExposedSource" return="java.lang.Object"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Returns an arbitrary object containing information about the "place" where this key was
+ exposed. Used by Guice in the production of descriptive error messages.
+
+ <p>Tools might specially handle types they know about; {@code StackTraceElement} is a good
+ example. Tools should simply call {@code toString()} on the source object if the type is
+ unfamiliar.
+
+ @param key one of the keys exposed by this module.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A private collection of elements that are hidden from the enclosing injector or module by
+ default. See {@link com.google.inject.PrivateModule PrivateModule} for details.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.PrivateElements -->
+  <!-- start interface com.google.inject.spi.ProviderBinding -->
+  <interface name="ProviderBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getProvidedKey" return="com.google.inject.Key&lt;?&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key whose binding is used to {@link Provider#get provide instances}. That binding
+ can be retrieved from an injector using {@link com.google.inject.Injector#getBinding(Key)
+ Injector.getBinding(providedKey)}]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a {@link Provider} that delegates to the binding for the provided type. This binding
+ is used whenever a {@code Provider<T>} is injected (as opposed to injecting {@code T} directly).
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderBinding -->
+  <!-- start interface com.google.inject.spi.ProviderInstanceBinding -->
+  <interface name="ProviderInstanceBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getProviderInstance" return="com.google.inject.Provider&lt;? extends T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="Use {@link #getUserSuppliedProvider} instead.">
+      <doc>
+      <![CDATA[If the user supplied a JSR330 binding, then this will wrap that one. To always return the
+ user-supplied provider, use {@link #getUserSuppliedProvider}.
+ 
+ @deprecated Use {@link #getUserSuppliedProvider} instead.]]>
+      </doc>
+    </method>
+    <method name="getUserSuppliedProvider" return="javax.inject.Provider&lt;? extends T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the user-supplied, unscoped provider.]]>
+      </doc>
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the field and method injection points of the provider, injected at injector-creation
+ time only.
+
+ @return a possibly empty set]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a provider instance. The provider's {@code get} method is invoked to resolve
+ injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderInstanceBinding -->
+  <!-- start interface com.google.inject.spi.ProviderKeyBinding -->
+  <interface name="ProviderKeyBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <method name="getProviderKey" return="com.google.inject.Key&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key used to resolve the provider's binding. That binding can be retrieved from an
+ injector using {@link com.google.inject.Injector#getBinding(Key)
+ Injector.getBinding(providerKey)}]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A binding to a provider key. To resolve injections, the provider key is first resolved, then that
+ provider's {@code get} method is invoked.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderKeyBinding -->
+  <!-- start class com.google.inject.spi.ProviderLookup -->
+  <class name="ProviderLookup" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="ProviderLookup" type="java.lang.Object, com.google.inject.Key&lt;T&gt;"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="initializeDelegate"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="delegate" type="com.google.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Sets the actual provider.
+
+ @throws IllegalStateException if the delegate is already set]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="getDelegate" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the delegate provider, or {@code null} if it has not yet been initialized. The delegate
+ will be initialized when this element is processed, or otherwise used to create an injector.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the looked up provider. The result is not valid until this lookup has been initialized,
+ which usually happens when the injector is created. The provider will throw an {@code
+ IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A lookup of the provider for a type. Lookups are created explicitly in a module using
+ {@link com.google.inject.Binder#getProvider(Class) getProvider()} statements:
+ <pre>
+     Provider&lt;PaymentService&gt; paymentServiceProvider
+         = getProvider(PaymentService.class);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ProviderLookup -->
+  <!-- start interface com.google.inject.spi.ProviderWithDependencies -->
+  <interface name="ProviderWithDependencies"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Provider&lt;T&gt;"/>
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <doc>
+    <![CDATA[A provider with dependencies on other injected types. If a {@link Provider} has dependencies that
+ aren't specified in injections, this interface should be used to expose all dependencies.
+
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderWithDependencies -->
+  <!-- start interface com.google.inject.spi.ProviderWithExtensionVisitor -->
+  <interface name="ProviderWithExtensionVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Provider&lt;T&gt;"/>
+    <method name="acceptExtensionVisitor" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;B, V&gt;"/>
+      <param name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends B&gt;"/>
+      <doc>
+      <![CDATA[Instructs the extension determine if the visitor is an instance of a custom
+ extension visitor, and if so, visit it using that method. If the visitor is
+ not an instance of the custom extension visitor, this method <b>MUST</b>
+ call visitor.visit(binding).
+ <p> 
+ Due to issues with generics, the type parameters of this method do not
+ relate to the type of the provider. In practice, the 'B' type will always
+ be a supertype of 'T'.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A Provider that is part of an extension which supports a custom
+ BindingTargetVisitor.
+ <p> 
+ When an extension binds a provider instance, the provider can implement this
+ interface to allow users using the
+ {@link Binding#acceptTargetVisitor(BindingTargetVisitor)} method to visit a
+ custom visitor designed for that extension. A typical implementation within
+ the extension would look like
+ <pre> 
+ &lt;V, B> V acceptExtensionVisitor(BindingTargetVisitor&lt;B, V> visitor, ProviderInstanceBinding&lt;? extends B> binding) {
+   if(visitor instanceof MyCustomExtensionVisitor) {
+     return ((MyCustomExtensionVisitor&lt;B, V>)visitor).visitCustomExtension(customProperties, binding);
+   } else {
+     return visitor.visit(binding);
+   }
+ }</pre> 
+ 'MyCustomExtensionVisitor' in the example above would be an interface the
+ extension provides that users can implement in order to be notified of custom
+ extension information. These visitor interfaces must extend from
+ BindingTargetVisitor.
+
+ @since 3.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProviderWithExtensionVisitor -->
+  <!-- start interface com.google.inject.spi.ProvidesMethodBinding -->
+  <interface name="ProvidesMethodBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.HasDependencies"/>
+    <method name="getMethod" return="java.lang.reflect.Method"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the method this binding uses.]]>
+      </doc>
+    </method>
+    <method name="getEnclosingInstance" return="java.lang.Object"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the instance of the object the method is defined in.]]>
+      </doc>
+    </method>
+    <method name="getKey" return="com.google.inject.Key&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the key of the binding.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[An {@literal @}{@link Provides} binding.
+ 
+ @since 4.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProvidesMethodBinding -->
+  <!-- start interface com.google.inject.spi.ProvidesMethodTargetVisitor -->
+  <interface name="ProvidesMethodTargetVisitor"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.BindingTargetVisitor&lt;T, V&gt;"/>
+    <method name="visit" return="V"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providesMethodBinding" type="com.google.inject.spi.ProvidesMethodBinding&lt;? extends T&gt;"/>
+      <doc>
+      <![CDATA[Visits an {@link ProvidesMethodBinding} created with an {@literal @}{@link Provides} method.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[A visitor for the {@literal @}{@link Provides} bindings.
+ <p>
+ If your {@link BindingTargetVisitor} implements this interface, bindings created by using
+ {@code @Provides} will be visited through this interface.
+
+ @since 4.0
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProvidesMethodTargetVisitor -->
+  <!-- start interface com.google.inject.spi.ProvisionListener -->
+  <interface name="ProvisionListener"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="onProvision"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="provision" type="com.google.inject.spi.ProvisionListener.ProvisionInvocation&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Invoked by Guice when an object requires provisioning. Provisioning occurs
+ when Guice locates and injects the dependencies for a binding. For types
+ bound to a Provider, provisioning encapsulates the {@link Provider#get}
+ method. For toInstance or constant bindings, provisioning encapsulates
+ the injecting of {@literal @}{@code Inject}ed fields or methods.
+ For other types, provisioning encapsulates the construction of the
+ object. If a type is bound within a {@link Scope}, provisioning depends on
+ the scope. Types bound in Singleton scope will only be provisioned once.
+ Types bound in no scope will be provisioned every time they are injected.
+ Other scopes define their own behavior for provisioning.
+ <p>
+ To perform the provision, call {@link ProvisionInvocation#provision()}.
+ If you do not explicitly call provision, it will be automatically done after
+ this method returns.  It is an error to call provision more than once.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Listens for provisioning of objects. Useful for gathering timing information
+ about provisioning, post-provision initialization, and more.
+ 
+ @author sameb@google.com (Sam Berlin)
+ @since 4.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.ProvisionListener -->
+  <!-- start class com.google.inject.spi.ProvisionListener.ProvisionInvocation -->
+  <class name="ProvisionListener.ProvisionInvocation" extends="java.lang.Object"
+    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="ProvisionInvocation"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="getBinding" return="com.google.inject.Binding&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the Binding this is provisioning.
+ <p>
+ You must not call {@link Provider#get()} on the provider returned by
+ {@link Binding#getProvider}, otherwise you will get confusing error messages.]]>
+      </doc>
+    </method>
+    <method name="provision" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Performs the provision, returning the object provisioned.]]>
+      </doc>
+    </method>
+    <method name="getDependencyChain" return="java.util.List&lt;com.google.inject.spi.DependencyAndSource&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the dependency chain that led to this object being provisioned.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Encapsulates a single act of provisioning.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ProvisionListener.ProvisionInvocation -->
+  <!-- start class com.google.inject.spi.ProvisionListenerBinding -->
+  <class name="ProvisionListenerBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getListeners" return="java.util.List&lt;com.google.inject.spi.ProvisionListener&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the registered listeners.]]>
+      </doc>
+    </method>
+    <method name="getBindingMatcher" return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.Binding&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the binding matcher which chooses which bindings the listener should be notified of.]]>
+      </doc>
+    </method>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="R"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;R&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Binds keys (picked using a Matcher) to a provision listener. Listeners are created explicitly in
+ a module using {@link Binder#bindListener(Matcher, ProvisionListener...)} statements:
+
+ @author sameb@google.com (Sam Berlin)
+ @since 4.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ProvisionListenerBinding -->
+  <!-- start class com.google.inject.spi.RequireAtInjectOnConstructorsOption -->
+  <class name="RequireAtInjectOnConstructorsOption" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to require explicit {@literal @}{@link Inject} annotations on constructors.
+
+ @author sameb@google.com (Sam Berlin)
+ @since 4.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.RequireAtInjectOnConstructorsOption -->
+  <!-- start class com.google.inject.spi.RequireExactBindingAnnotationsOption -->
+  <class name="RequireExactBindingAnnotationsOption" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to require exact binding annotations.
+
+ @author sameb@google.com (Sam Berlin)
+ @since 4.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.RequireExactBindingAnnotationsOption -->
+  <!-- start class com.google.inject.spi.RequireExplicitBindingsOption -->
+  <class name="RequireExplicitBindingsOption" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to require explicit bindings.
+
+ @author sameb@google.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.RequireExplicitBindingsOption -->
+  <!-- start class com.google.inject.spi.ScopeBinding -->
+  <class name="ScopeBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getAnnotationType" return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getScope" return="com.google.inject.Scope"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Registration of a scope annotation with the scope that implements it. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#bindScope(Class, Scope) bindScope()}
+ statements:
+ <pre>
+     Scope recordScope = new RecordScope();
+     bindScope(RecordScoped.class, new RecordScope());</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.ScopeBinding -->
+  <!-- start class com.google.inject.spi.StaticInjectionRequest -->
+  <class name="StaticInjectionRequest" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getType" return="java.lang.Class&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getInjectionPoints" return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="ConfigurationException" type="com.google.inject.ConfigurationException"/>
+      <doc>
+      <![CDATA[Returns the static methods and fields of {@code type} that will be injected to fulfill this
+ request.
+
+ @return a possibly empty set of injection points. The set has a specified iteration order. All
+      fields are returned and then all methods. Within the fields, supertype fields are returned
+      before subtype fields. Similarly, supertype methods are returned before subtype methods.
+ @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
+      a field with multiple binding annotations. The exception's {@link
+      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
+      of the valid injection points.]]>
+      </doc>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[A request to inject the static fields and methods of a type. Requests are created
+ explicitly in a module using {@link com.google.inject.Binder#requestStaticInjection(Class[])
+ requestStaticInjection()} statements:
+ <pre>
+     requestStaticInjection(MyLegacyService.class);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.StaticInjectionRequest -->
+  <!-- start class com.google.inject.spi.Toolable -->
+  <class name="Toolable"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Instructs an {@link Injector} running in {@link Stage#TOOL} that a method should be injected.
+ This is typically useful for for extensions to Guice that perform additional validation in an
+ injected method or field.  This only applies to objects that are already constructed when
+ bindings are created (ie., something bound using {@link
+ com.google.inject.binder.LinkedBindingBuilder#toProvider toProvider}, {@link
+ com.google.inject.binder.LinkedBindingBuilder#toInstance toInstance}, or {@link
+ com.google.inject.Binder#requestInjection requestInjection}.
+ 
+ @author sberlin@gmail.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.Toolable -->
+  <!-- start interface com.google.inject.spi.TypeConverter -->
+  <interface name="TypeConverter"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="convert" return="java.lang.Object"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="value" type="java.lang.String"/>
+      <param name="toType" type="com.google.inject.TypeLiteral&lt;?&gt;"/>
+      <doc>
+      <![CDATA[Converts a string value. Throws an exception if a conversion error occurs.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Converts constant string values to a different type.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeConverter -->
+  <!-- start class com.google.inject.spi.TypeConverterBinding -->
+  <class name="TypeConverterBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <constructor name="TypeConverterBinding" type="java.lang.Object, com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;, com.google.inject.spi.TypeConverter"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[@since 3.0]]>
+      </doc>
+    </constructor>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTypeMatcher" return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getTypeConverter" return="com.google.inject.spi.TypeConverter"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="toString" return="java.lang.String"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Registration of type converters for matching target types. Instances are created
+ explicitly in a module using {@link com.google.inject.Binder#convertToTypes(Matcher,
+ TypeConverter) convertToTypes()} statements:
+ <pre>
+     convertToTypes(Matchers.only(TypeLiteral.get(DateTime.class)), new DateTimeConverter());</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.TypeConverterBinding -->
+  <!-- start interface com.google.inject.spi.TypeEncounter -->
+  <interface name="TypeEncounter"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="addError"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="java.lang.String"/>
+      <param name="arguments" type="java.lang.Object[]"/>
+      <doc>
+      <![CDATA[Records an error message for type {@code I} which will be presented to the user at a later
+ time. Unlike throwing an exception, this enable us to continue configuring the Injector and
+ discover more errors. Uses {@link String#format(String, Object[])} to insert the arguments
+ into the message.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="t" type="java.lang.Throwable"/>
+      <doc>
+      <![CDATA[Records an exception for type {@code I}, the full details of which will be logged, and the
+ message of which will be presented to the user at a later time. If your type listener calls
+ something that you worry may fail, you should catch the exception and pass it to this method.]]>
+      </doc>
+    </method>
+    <method name="addError"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="message" type="com.google.inject.spi.Message"/>
+      <doc>
+      <![CDATA[Records an error message to be presented to the user at a later time.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="key" type="com.google.inject.Key&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection key. The returned
+ provider will not be valid until the injector has been created. The provider will throw an
+ {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the provider used to obtain instances for the given injection type. The returned
+ provider will not be valid until the injetor has been created. The provider will throw an
+ {@code IllegalStateException} if you try to use it beforehand.]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ injector has been created. The members injector will throw an {@code IllegalStateException}
+ if you try to use it beforehand.
+
+ @param typeLiteral type to get members injector for]]>
+      </doc>
+    </method>
+    <method name="getMembersInjector" return="com.google.inject.MembersInjector&lt;T&gt;"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns the members injector used to inject dependencies into methods and fields on instances
+ of the given type {@code T}. The returned members injector will not be valid until the main
+ injector has been created. The members injector will throw an {@code IllegalStateException}
+ if you try to use it beforehand.
+
+ @param type type to get members injector for]]>
+      </doc>
+    </method>
+    <method name="register"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="membersInjector" type="com.google.inject.MembersInjector&lt;? super I&gt;"/>
+      <doc>
+      <![CDATA[Registers a members injector for type {@code I}. Guice will use the members injector after its
+ performed its own injections on an instance of {@code I}.]]>
+      </doc>
+    </method>
+    <method name="register"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="listener" type="com.google.inject.spi.InjectionListener&lt;? super I&gt;"/>
+      <doc>
+      <![CDATA[Registers an injection listener for type {@code I}. Guice will notify the listener after all
+ injections have been performed on an instance of {@code I}.]]>
+      </doc>
+    </method>
+    <method name="bindInterceptor"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"/>
+      <param name="interceptors" type="org.aopalliance.intercept.MethodInterceptor[]"/>
+      <doc>
+      <![CDATA[Binds method interceptor[s] to methods matched in type {@code I} and its supertypes. A
+ method is eligible for interception if:
+
+ <ul>
+  <li>Guice created the instance the method is on</li>
+  <li>Neither the enclosing type nor the method is final</li>
+  <li>And the method is package-private or more accessible</li>
+ </ul>
+
+ @param methodMatcher matches methods the interceptor should apply to. For
+     example: {@code annotatedWith(Transactional.class)}.
+ @param interceptors to bind]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Context of an injectable type encounter. Enables reporting errors, registering injection
+ listeners and binding method interceptors for injectable type {@code I}. It is an error to use
+ an encounter after the {@link TypeListener#hear(TypeLiteral, TypeEncounter) hear()} method has
+ returned.
+
+ @param <I> the injectable type encountered
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeEncounter -->
+  <!-- start interface com.google.inject.spi.TypeListener -->
+  <interface name="TypeListener"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="hear"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="com.google.inject.TypeLiteral&lt;I&gt;"/>
+      <param name="encounter" type="com.google.inject.spi.TypeEncounter&lt;I&gt;"/>
+      <doc>
+      <![CDATA[Invoked when Guice encounters a new type eligible for constructor or members injection.
+ Called during injector creation (or afterwords if Guice encounters a type at run time and
+ creates a JIT binding).
+
+ @param type encountered by Guice
+ @param encounter context of this encounter, enables reporting errors, registering injection
+     listeners and binding method interceptors for {@code type}.
+
+ @param <I> the injectable type]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Listens for Guice to encounter injectable types. If a given type has its constructor injected in
+ one situation but only its methods and fields injected in another, Guice will notify this
+ listener once.
+
+ <p>Useful for extra type checking, {@linkplain TypeEncounter#register(InjectionListener)
+ registering injection listeners}, and {@linkplain TypeEncounter#bindInterceptor(
+ com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])
+ binding method interceptors}.
+ 
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.TypeListener -->
+  <!-- start class com.google.inject.spi.TypeListenerBinding -->
+  <class name="TypeListenerBinding" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.spi.Element"/>
+    <method name="getListener" return="com.google.inject.spi.TypeListener"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the registered listener.]]>
+      </doc>
+    </method>
+    <method name="getTypeMatcher" return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Returns the type matcher which chooses which types the listener should be notified of.]]>
+      </doc>
+    </method>
+    <method name="getSource" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="acceptVisitor" return="T"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;"/>
+    </method>
+    <method name="applyTo"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <doc>
+    <![CDATA[Binds types (picked using a Matcher) to an type listener. Registrations are created explicitly in
+ a module using {@link com.google.inject.Binder#bindListener(Matcher, TypeListener)} statements:
+
+ <pre>
+     register(only(new TypeLiteral&lt;PaymentService&lt;CreditCard>>() {}), listener);</pre>
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spi.TypeListenerBinding -->
+  <!-- start interface com.google.inject.spi.UntargettedBinding -->
+  <interface name="UntargettedBinding"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="com.google.inject.Binding&lt;T&gt;"/>
+    <doc>
+    <![CDATA[An untargetted binding. This binding indicates that the injector should use its implicit binding
+ strategies to resolve injections.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.spi.UntargettedBinding -->
+</package>
+<package name="com.google.inject.spring">
+  <!-- start class com.google.inject.spring.SpringIntegration -->
+  <class name="SpringIntegration" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="fromSpring" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="type" type="java.lang.Class&lt;T&gt;"/>
+      <param name="name" type="java.lang.String"/>
+      <doc>
+      <![CDATA[Creates a provider which looks up objects from Spring using the given name.
+ Expects a binding to {@link
+ org.springframework.beans.factory.BeanFactory}. Example usage:
+
+ <pre>
+ bind(DataSource.class)
+   .toProvider(fromSpring(DataSource.class, "dataSource"));
+ </pre>]]>
+      </doc>
+    </method>
+    <method name="bindAll"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+      <param name="beanFactory" type="ListableBeanFactory"/>
+      <doc>
+      <![CDATA[Binds all Spring beans from the given factory by name. For a Spring bean
+ named "foo", this method creates a binding to the bean's type and
+ {@code @Named("foo")}.
+
+ @see com.google.inject.name.Named
+ @see com.google.inject.name.Names#named(String)]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Integrates Guice with Spring.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.spring.SpringIntegration -->
+</package>
+<package name="com.google.inject.struts2">
+  <!-- start class com.google.inject.struts2.GuiceObjectFactory -->
+  <class name="GuiceObjectFactory" extends="ObjectFactory"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="Use {@link com.google.inject.servlet.Struts2Factory} instead.">
+    <constructor name="GuiceObjectFactory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="isNoArgConstructorRequired" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassInstance" return="java.lang.Class"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException"/>
+    </method>
+    <method name="buildBean" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class"/>
+      <param name="extraContext" type="java.util.Map"/>
+    </method>
+    <method name="buildInterceptor" return="Interceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorConfig" type="InterceptorConfig"/>
+      <param name="interceptorRefParams" type="java.util.Map"/>
+      <exception name="ConfigurationException" type="ConfigurationException"/>
+    </method>
+    <doc>
+    <![CDATA[@deprecated Use {@link com.google.inject.servlet.Struts2Factory} instead.]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.struts2.GuiceObjectFactory -->
+  <!-- start class com.google.inject.struts2.Struts2Factory -->
+  <class name="Struts2Factory" extends="ObjectFactory"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Struts2Factory"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="isNoArgConstructorRequired" return="boolean"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </method>
+    <method name="getClassInstance" return="java.lang.Class&lt;?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="name" type="java.lang.String"/>
+      <exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException"/>
+    </method>
+    <method name="buildBean" return="java.lang.Object"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="clazz" type="java.lang.Class"/>
+      <param name="extraContext" type="java.util.Map&lt;java.lang.String, java.lang.Object&gt;"/>
+    </method>
+    <method name="buildInterceptor" return="Interceptor"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interceptorConfig" type="InterceptorConfig"/>
+      <param name="interceptorRefParams" type="java.util.Map"/>
+      <exception name="ConfigurationException" type="ConfigurationException"/>
+    </method>
+    <doc>
+    <![CDATA[Cleanup up version from Bob's GuiceObjectFactory. Now works properly with
+ GS2 and fixes several bugs.
+
+ @author dhanji@gmail.com
+ @author benmccann.com]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.struts2.Struts2Factory -->
+  <!-- start class com.google.inject.struts2.Struts2GuicePluginModule -->
+  <class name="Struts2GuicePluginModule" extends="com.google.inject.AbstractModule"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Struts2GuicePluginModule"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="configure"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="protected"
+      deprecated="not deprecated">
+    </method>
+    <doc>
+    <![CDATA[Initializes the Struts 2 Guice Plugin.
+ Must be added to the injector returned by
+     {@link GuiceServletContextListener.getInjector()}.
+
+ @author benmccann.com]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.struts2.Struts2GuicePluginModule -->
+</package>
+<package name="com.google.inject.throwingproviders">
+  <!-- start interface com.google.inject.throwingproviders.CheckedProvider -->
+  <interface name="CheckedProvider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="get" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="Exception" type="java.lang.Exception"/>
+    </method>
+    <doc>
+    <![CDATA[Alternative to the Guice {@link com.google.inject.Provider} that throws
+ a checked Exception. Users may not inject {@code T} directly.
+
+ <p>This interface must be extended to use application-specific exception types.
+ Such subinterfaces may not define new methods, but may narrow the exception type.
+ <pre>
+ public interface RemoteProvider&lt;T&gt; extends CheckedProvider&lt;T&gt; { 
+   T get() throws CustomExceptionOne, CustomExceptionTwo;
+ }
+ </pre>
+
+ <p>When this type is bound using {@link ThrowingProviderBinder}, the value returned
+ or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get}
+ will invoked at most once within each scope.
+ 
+ @since 3.0]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.throwingproviders.CheckedProvider -->
+  <!-- start class com.google.inject.throwingproviders.CheckedProvides -->
+  <class name="CheckedProvides"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[Annotates methods of a {@link Module} to create a {@link CheckedProvider}
+ method binding that can throw exceptions. The method's return type is bound
+ to a {@link CheckedProvider} that can be injected. Guice will pass
+ dependencies to the method as parameters. Install {@literal @}CheckedProvides
+ methods by using
+ {@link ThrowingProviderBinder#forModule(com.google.inject.Module)} on the
+ module where the methods are declared.
+ 
+ @author sameb@google.com (Sam Berlin)
+ @since 3.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.CheckedProvides -->
+  <!-- start class com.google.inject.throwingproviders.ThrowingInject -->
+  <class name="ThrowingInject"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <implements name="java.lang.annotation.Annotation"/>
+    <doc>
+    <![CDATA[A version of {@literal @}{@link Inject} designed for ThrowingProviders.  Use by:
+ <pre><code>ThrowingProviderBinder.create(binder())
+    .bind(RemoteProvider.class, Customer.class)
+    .providing(CustomerImpl.class);
+ </code></pre>
+ where CustomerImpl has a constructor annotated with ThrowingInject.
+
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.ThrowingInject -->
+  <!-- start interface com.google.inject.throwingproviders.ThrowingProvider -->
+  <interface name="ThrowingProvider"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="use {@link CheckedProvider} instead.">
+    <implements name="com.google.inject.throwingproviders.CheckedProvider&lt;T&gt;"/>
+    <method name="get" return="T"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <exception name="Exception" type="java.lang.Exception"/>
+    </method>
+    <doc>
+    <![CDATA[Alternative to the Guice {@link com.google.inject.Provider} that throws
+ a checked Exception. Users may not inject {@code T} directly.
+
+ <p>This interface must be extended to use application-specific exception types.
+ Such subinterfaces may not define new methods:
+ <pre>
+ public interface RemoteProvider&lt;T&gt; extends ThrowingProvider&lt;T, RemoteException&gt; { }
+ </pre>
+
+ <p>When this type is bound using {@link ThrowingProviderBinder}, the value returned
+ or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get}
+ will invoked at most once within each scope.
+
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)
+ @deprecated use {@link CheckedProvider} instead.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.throwingproviders.ThrowingProvider -->
+  <!-- start class com.google.inject.throwingproviders.ThrowingProviderBinder -->
+  <class name="ThrowingProviderBinder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="create" return="com.google.inject.throwingproviders.ThrowingProviderBinder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="binder" type="com.google.inject.Binder"/>
+    </method>
+    <method name="forModule" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="module" type="com.google.inject.Module"/>
+      <doc>
+      <![CDATA[Returns a module that installs {@literal @}{@link CheckedProvides} methods.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, ?&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="Use {@link #bind(Class, Class)} or {@link #bind(Class, TypeLiteral)} instead.">
+      <param name="interfaceType" type="java.lang.Class&lt;P&gt;"/>
+      <param name="clazz" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[@deprecated Use {@link #bind(Class, Class)} or {@link #bind(Class, TypeLiteral)} instead.]]>
+      </doc>
+    </method>
+    <method name="bind" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interfaceType" type="java.lang.Class&lt;P&gt;"/>
+      <param name="clazz" type="java.lang.Class&lt;T&gt;"/>
+    </method>
+    <method name="bind" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="interfaceType" type="java.lang.Class&lt;P&gt;"/>
+      <param name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;"/>
+    </method>
+    <doc>
+    <![CDATA[<p>Builds a binding for a {@link CheckedProvider}.
+ 
+ <p>You can use a fluent API and custom providers:
+ <pre><code>ThrowingProviderBinder.create(binder())
+    .bind(RemoteProvider.class, Customer.class)
+    .to(RemoteCustomerProvider.class)
+    .in(RequestScope.class);
+ </code></pre>
+ or, you can use throwing provider methods:
+ <pre><code>class MyModule extends AbstractModule {
+   configure() {
+     ThrowingProviderBinder.install(this, binder());
+   }
+   
+   {@literal @}CheckedProvides(RemoteProvider.class)
+   {@literal @}RequestScope
+   Customer provideCustomer(FlakyCustomerCreator creator) throws RemoteException {
+     return creator.getCustomerOrThrow();
+   }
+ }
+ </code></pre>
+ You also can declare that a CheckedProvider construct
+ a particular class whose constructor throws an exception:
+ <pre><code>ThrowingProviderBinder.create(binder())
+    .bind(RemoteProvider.class, Customer.class)
+    .providing(CustomerImpl.class)
+    .in(RequestScope.class);
+ </code></pre>
+ 
+ @author jmourits@google.com (Jerome Mourits)
+ @author jessewilson@google.com (Jesse Wilson)
+ @author sameb@google.com (Sam Berlin)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.ThrowingProviderBinder -->
+  <!-- start class com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder -->
+  <class name="ThrowingProviderBinder.SecondaryBinder" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="SecondaryBinder" type="java.lang.Class&lt;P&gt;, java.lang.reflect.Type"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="annotatedWith" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"/>
+    </method>
+    <method name="annotatedWith" return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="annotation" type="java.lang.annotation.Annotation"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="target" type="P extends com.google.inject.throwingproviders.CheckedProvider"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetType" type="java.lang.Class&lt;? extends P&gt;"/>
+    </method>
+    <method name="providing" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="cxtorClass" type="java.lang.Class&lt;? extends T&gt;"/>
+    </method>
+    <method name="providing" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="cxtorLiteral" type="com.google.inject.TypeLiteral&lt;? extends T&gt;"/>
+    </method>
+    <method name="to" return="com.google.inject.binder.ScopedBindingBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="targetKey" type="com.google.inject.Key&lt;? extends P&gt;"/>
+    </method>
+  </class>
+  <!-- end class com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder -->
+</package>
+<package name="com.google.inject.tools.jmx">
+  <!-- start interface com.google.inject.tools.jmx.ManagedBindingMBean -->
+  <interface name="ManagedBindingMBean"    abstract="true"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="getSource" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the source of this binding.]]>
+      </doc>
+    </method>
+    <method name="getProvider" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the provider to which this binding is bound.]]>
+      </doc>
+    </method>
+    <method name="getKey" return="java.lang.String"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <doc>
+      <![CDATA[Gets the binding key.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[JMX interface to bindings.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.tools.jmx.ManagedBindingMBean -->
+  <!-- start class com.google.inject.tools.jmx.Manager -->
+  <class name="Manager" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="false" visibility="public"
+    deprecated="not deprecated">
+    <constructor name="Manager"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+    </constructor>
+    <method name="manage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="domain" type="java.lang.String"/>
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Registers all the bindings of an Injector with the platform MBean server.
+ Consider using the name of your root {@link Module} class as the domain.]]>
+      </doc>
+    </method>
+    <method name="manage"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="server" type="javax.management.MBeanServer"/>
+      <param name="domain" type="java.lang.String"/>
+      <param name="injector" type="com.google.inject.Injector"/>
+      <doc>
+      <![CDATA[Registers all the bindings of an Injector with the given MBean server.
+ Consider using the name of your root {@link Module} class as the domain.]]>
+      </doc>
+    </method>
+    <method name="main"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="args" type="java.lang.String[]"/>
+      <exception name="Exception" type="java.lang.Exception"/>
+      <doc>
+      <![CDATA[Run with no arguments for usage instructions.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Provides a JMX interface to Guice.
+
+ @author crazybob@google.com (Bob Lee)]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.tools.jmx.Manager -->
+</package>
+<package name="com.google.inject.util">
+  <!-- start class com.google.inject.util.Modules -->
+  <class name="Modules" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="override" return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a builder that creates a module that overlays override modules over the given
+ modules. If a key is bound in both sets of modules, only the binding from the override modules
+ is kept. If a single {@link PrivateModule} is supplied or all elements are from
+ a single {@link PrivateBinder}, then this will overwrite the private bindings.
+ Otherwise, private bindings will not be overwritten unless they are exposed. 
+ This can be used to replace the bindings of a production module with test bindings:
+ <pre>
+ Module functionalTestModule
+     = Modules.override(new ProductionModule()).with(new TestModule());
+ </pre>
+
+ <p>Prefer to write smaller modules that can be reused and tested without overrides.
+
+ @param modules the modules whose bindings are open to be overridden]]>
+      </doc>
+    </method>
+    <method name="override" return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a builder that creates a module that overlays override modules over the given
+ modules. If a key is bound in both sets of modules, only the binding from the override modules
+ is kept. If a single {@link PrivateModule} is supplied or all elements are from
+ a single {@link PrivateBinder}, then this will overwrite the private bindings.
+ Otherwise, private bindings will not be overwritten unless they are exposed. 
+ This can be used to replace the bindings of a production module with test bindings:
+ <pre>
+ Module functionalTestModule
+     = Modules.override(getProductionModules()).with(getTestModules());
+ </pre>
+
+ <p>Prefer to write smaller modules that can be reused and tested without overrides.
+
+ @param modules the modules whose bindings are open to be overridden]]>
+      </doc>
+    </method>
+    <method name="combine" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[Returns a new module that installs all of {@code modules}.]]>
+      </doc>
+    </method>
+    <method name="combine" return="com.google.inject.Module"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[Returns a new module that installs all of {@code modules}.]]>
+      </doc>
+    </method>
+    <field name="EMPTY_MODULE" type="com.google.inject.Module"
+      transient="false" volatile="false"
+      static="true" final="true" visibility="public"
+      deprecated="not deprecated">
+    </field>
+    <doc>
+    <![CDATA[Static utility methods for creating and working with instances of {@link Module}.
+
+ @author jessewilson@google.com (Jesse Wilson)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Modules -->
+  <!-- start interface com.google.inject.util.Modules.OverriddenModuleBuilder -->
+  <interface name="Modules.OverriddenModuleBuilder"    abstract="true"
+    static="true" final="false" visibility="public"
+    deprecated="not deprecated">
+    <method name="with" return="com.google.inject.Module"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="overrides" type="com.google.inject.Module[]"/>
+      <doc>
+      <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+      </doc>
+    </method>
+    <method name="with" return="com.google.inject.Module"
+      abstract="true" native="false" synchronized="false"
+      static="false" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="overrides" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;"/>
+      <doc>
+      <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[See the EDSL example at {@link Modules#override(Module[]) override()}.]]>
+    </doc>
+  </interface>
+  <!-- end interface com.google.inject.util.Modules.OverriddenModuleBuilder -->
+  <!-- start class com.google.inject.util.Providers -->
+  <class name="Providers" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="of" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="instance" type="T"/>
+      <doc>
+      <![CDATA[Returns a provider which always provides {@code instance}.  This should not
+ be necessary to use in your application, but is helpful for several types
+ of unit tests.
+
+ @param instance the instance that should always be provided.  This is also
+     permitted to be null, to enable aggressive testing, although in real
+     life a Guice-supplied Provider will never return null.]]>
+      </doc>
+    </method>
+    <method name="guicify" return="com.google.inject.Provider&lt;T&gt;"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="provider" type="javax.inject.Provider&lt;T&gt;"/>
+      <doc>
+      <![CDATA[Returns a Guice-friendly {@code com.google.inject.Provider} for the given
+ JSR-330 {@code javax.inject.Provider}. The converse method is unnecessary,
+ since Guice providers directly implement the JSR-330 interface.
+ 
+ @since 3.0]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Static utility methods for creating and working with instances of
+ {@link Provider}.
+
+ @author Kevin Bourrillion (kevinb9n@gmail.com)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Providers -->
+  <!-- start class com.google.inject.util.Types -->
+  <class name="Types" extends="java.lang.Object"
+    abstract="false"
+    static="false" final="true" visibility="public"
+    deprecated="not deprecated">
+    <method name="newParameterizedType" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="rawType" type="java.lang.reflect.Type"/>
+      <param name="typeArguments" type="java.lang.reflect.Type[]"/>
+      <doc>
+      <![CDATA[Returns a new parameterized type, applying {@code typeArguments} to
+ {@code rawType}. The returned type does not have an owner type.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="newParameterizedTypeWithOwner" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="ownerType" type="java.lang.reflect.Type"/>
+      <param name="rawType" type="java.lang.reflect.Type"/>
+      <param name="typeArguments" type="java.lang.reflect.Type[]"/>
+      <doc>
+      <![CDATA[Returns a new parameterized type, applying {@code typeArguments} to
+ {@code rawType} and enclosed by {@code ownerType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="arrayOf" return="java.lang.reflect.GenericArrayType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="componentType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns an array type whose elements are all instances of
+ {@code componentType}.
+
+ @return a {@link java.io.Serializable serializable} generic array type.]]>
+      </doc>
+    </method>
+    <method name="subtypeOf" return="java.lang.reflect.WildcardType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bound" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type that represents an unknown type that extends {@code bound}.
+ For example, if {@code bound} is {@code CharSequence.class}, this returns
+ {@code ? extends CharSequence}. If {@code bound} is {@code Object.class},
+ this returns {@code ?}, which is shorthand for {@code ? extends Object}.]]>
+      </doc>
+    </method>
+    <method name="supertypeOf" return="java.lang.reflect.WildcardType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="bound" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type that represents an unknown supertype of {@code bound}. For
+ example, if {@code bound} is {@code String.class}, this returns {@code ?
+ super String}.]]>
+      </doc>
+    </method>
+    <method name="listOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elementType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link List} whose elements are of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="setOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="elementType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Set} whose elements are of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="mapOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="keyType" type="java.lang.reflect.Type"/>
+      <param name="valueType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Map} whose keys are of type
+ {@code keyType} and whose values are of type {@code valueType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <method name="providerOf" return="java.lang.reflect.ParameterizedType"
+      abstract="false" native="false" synchronized="false"
+      static="true" final="false" visibility="public"
+      deprecated="not deprecated">
+      <param name="providedType" type="java.lang.reflect.Type"/>
+      <doc>
+      <![CDATA[Returns a type modelling a {@link Provider} that provides elements of type
+ {@code elementType}.
+
+ @return a {@link java.io.Serializable serializable} parameterized type.]]>
+      </doc>
+    </method>
+    <doc>
+    <![CDATA[Static methods for working with types.
+
+ @author crazybob@google.com (Bob Lee)
+ @since 2.0]]>
+    </doc>
+  </class>
+  <!-- end class com.google.inject.util.Types -->
+</package>
+
+</api>
diff --git a/lib/aopalliance.jar b/lib/aopalliance.jar
new file mode 100644
index 0000000..578b1a0
--- /dev/null
+++ b/lib/aopalliance.jar
Binary files differ
diff --git a/lib/build/README b/lib/build/README
new file mode 100644
index 0000000..710272c
--- /dev/null
+++ b/lib/build/README
@@ -0,0 +1 @@
+These libraries are not needed at runtime.
diff --git a/lib/build/asm-5.0.3.jar b/lib/build/asm-5.0.3.jar
new file mode 100644
index 0000000..573535b
--- /dev/null
+++ b/lib/build/asm-5.0.3.jar
Binary files differ
diff --git a/lib/build/bnd-0.0.384.jar b/lib/build/bnd-0.0.384.jar
new file mode 100644
index 0000000..fa5e526
--- /dev/null
+++ b/lib/build/bnd-0.0.384.jar
Binary files differ
diff --git a/lib/build/cglib-3.1.jar b/lib/build/cglib-3.1.jar
new file mode 100644
index 0000000..25a5df1
--- /dev/null
+++ b/lib/build/cglib-3.1.jar
Binary files differ
diff --git a/lib/build/commons-logging-1.0.4.jar b/lib/build/commons-logging-1.0.4.jar
new file mode 100644
index 0000000..b73a80f
--- /dev/null
+++ b/lib/build/commons-logging-1.0.4.jar
Binary files differ
diff --git a/lib/build/easymock.jar b/lib/build/easymock.jar
new file mode 100644
index 0000000..c4159f5
--- /dev/null
+++ b/lib/build/easymock.jar
Binary files differ
diff --git a/lib/build/felix-2.0.5.jar b/lib/build/felix-2.0.5.jar
new file mode 100644
index 0000000..71e5a84
--- /dev/null
+++ b/lib/build/felix-2.0.5.jar
Binary files differ
diff --git a/lib/build/guava-testlib-16.0.1.jar b/lib/build/guava-testlib-16.0.1.jar
new file mode 100644
index 0000000..59150aa
--- /dev/null
+++ b/lib/build/guava-testlib-16.0.1.jar
Binary files differ
diff --git a/lib/build/guice-1.0.xml b/lib/build/guice-1.0.xml
new file mode 100644
index 0000000..176185a
--- /dev/null
+++ b/lib/build/guice-1.0.xml
@@ -0,0 +1,2984 @@
+<api>
+<package name="com.google.inject"
+>
+<class name="AbstractModule"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Module">
+</implements>
+<constructor name="AbstractModule"
+ type="com.google.inject.AbstractModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="clazz" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="binder"
+ return="com.google.inject.Binder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="builder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="install"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+</class>
+<interface name="Binder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="install"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+</interface>
+<interface name="Binding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="BindingAnnotation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="CreationException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CreationException"
+ type="com.google.inject.CreationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="errorMessages" type="java.util.Collection&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Guice"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="java.lang.Iterable&lt;com.google.inject.Module&gt;">
+</parameter>
+</method>
+</class>
+<class name="ImplementedBy"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="Inject"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<interface name="Injector"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="findBindingsByType"
+ return="java.util.List&lt;com.google.inject.Binding&lt;T&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBindings"
+ return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="injectMembers"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="Key"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</constructor>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</constructor>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="getAnnotation"
+ return="java.lang.annotation.Annotation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAnnotationType"
+ return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="Module"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+</interface>
+<class name="ProvidedBy"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<interface name="Provider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="Scope"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="scope"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+<parameter name="unscoped" type="com.google.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="ScopeAnnotation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="Scopes"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="SINGLETON"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Singleton"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="Stage"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.Stage[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="TypeLiteral"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="TypeLiteral"
+ type="com.google.inject.TypeLiteral"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<method name="get"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getType"
+ return="java.lang.reflect.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
+<package name="com.google.inject.binder"
+>
+<interface name="AnnotatedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.binder.LinkedBindingBuilder">
+</implements>
+<method name="annotatedWith"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="AnnotatedConstantBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="com.google.inject.binder.ConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.binder.ConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="ConstantBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="long">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="double">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="float">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="short">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="char">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="E">
+</parameter>
+</method>
+</interface>
+<interface name="LinkedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.binder.ScopedBindingBuilder">
+</implements>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetKey" type="com.google.inject.Key&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="toInstance"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="com.google.inject.Provider&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerType" type="java.lang.Class&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerKey" type="com.google.inject.Key&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ScopedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="asEagerSingleton"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="in"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="in"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+</interface>
+</package>
+<package name="com.google.inject.jndi"
+>
+<class name="JndiIntegration"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="fromJndi"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.matcher"
+>
+<class name="AbstractMatcher"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.matcher.Matcher">
+</implements>
+<constructor name="AbstractMatcher"
+ type="com.google.inject.matcher.AbstractMatcher"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="and"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="or"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+</class>
+<interface name="Matcher"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="and"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="matches"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="T">
+</parameter>
+</method>
+<method name="or"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+</interface>
+<class name="Matchers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="any"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="identicalTo"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="inPackage"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="java.lang.Package">
+</parameter>
+</method>
+<method name="not"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="only"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="returns"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.Method&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="returnType" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+</method>
+<method name="subclassesOf"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="superclass" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.name"
+>
+<class name="Named"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="Names"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="properties" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="bindProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="properties" type="java.util.Properties">
+</parameter>
+</method>
+<method name="named"
+ return="com.google.inject.name.Named"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.servlet"
+>
+<class name="GuiceFilter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceFilter"
+ type="com.google.inject.servlet.GuiceFilter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="doFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletRequest" type="ServletRequest">
+</parameter>
+<parameter name="servletResponse" type="ServletResponse">
+</parameter>
+<parameter name="filterChain" type="FilterChain">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterConfig" type="FilterConfig">
+</parameter>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+</class>
+<class name="RequestParameters"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="RequestScoped"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="ServletModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ServletModule"
+ type="com.google.inject.servlet.ServletModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<class name="ServletScopes"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="REQUEST"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SESSION"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SessionScoped"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+</package>
+<package name="com.google.inject.spi"
+>
+<class name="Message"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="getMessage"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSourceString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="SourceProvider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="source"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="SourceProviders"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="defaultSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSkippedClassNames"
+ return="java.util.Set&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="skip"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="clazz" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="withDefault"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sourceProvider" type="com.google.inject.spi.SourceProvider">
+</parameter>
+<parameter name="r" type="java.lang.Runnable">
+</parameter>
+</method>
+<field name="UNKNOWN_SOURCE"
+ type="java.lang.Object"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+</package>
+<package name="com.google.inject.tools.jmx"
+>
+<interface name="ManagedBindingMBean"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getKey"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Manager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Manager"
+ type="com.google.inject.tools.jmx.Manager"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="main"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+<method name="manage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="domain" type="java.lang.String">
+</parameter>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+<method name="manage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="server" type="javax.management.MBeanServer">
+</parameter>
+<parameter name="domain" type="java.lang.String">
+</parameter>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.util"
+>
+<class name="Annotations"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Annotations"
+ type="com.google.inject.util.Annotations"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="isRetainedAtRuntime"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</class>
+<class name="FinalizableSoftReference"
+ extends="java.lang.ref.SoftReference"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FinalizableSoftReference"
+ type="com.google.inject.util.FinalizableSoftReference"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="referent" type="T">
+</parameter>
+</constructor>
+</class>
+<class name="FinalizableWeakReference"
+ extends="java.lang.ref.WeakReference"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FinalizableWeakReference"
+ type="com.google.inject.util.FinalizableWeakReference"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="referent" type="T">
+</parameter>
+</constructor>
+</class>
+<interface name="Function"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="apply"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="from" type="F">
+</parameter>
+</method>
+</interface>
+<class name="GuiceFastClass"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceFastClass"
+ type="com.google.inject.util.GuiceFastClass"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="create"
+ return="FastClass"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class">
+</parameter>
+</method>
+<method name="create"
+ return="FastClass"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="loader" type="java.lang.ClassLoader">
+</parameter>
+<parameter name="type" type="java.lang.Class">
+</parameter>
+</method>
+</class>
+<class name="GuiceNamingPolicy"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceNamingPolicy"
+ type="com.google.inject.util.GuiceNamingPolicy"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getClassName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="source" type="java.lang.String">
+</parameter>
+<parameter name="key" type="java.lang.Object">
+</parameter>
+<parameter name="names" type="Predicate">
+</parameter>
+</method>
+</class>
+<class name="LineNumbers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="LineNumbers"
+ type="com.google.inject.util.LineNumbers"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cls" type="java.lang.Class">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</constructor>
+<method name="getFirstLine"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLineNumber"
+ return="java.lang.Integer"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Objects"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Objects"
+ type="com.google.inject.util.Objects"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="assertNoNulls"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="objects" type="java.lang.Object[]">
+</parameter>
+</method>
+<method name="equal"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="java.lang.Object">
+</parameter>
+<parameter name="b" type="java.lang.Object">
+</parameter>
+</method>
+<method name="nonNull"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="T">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="ReferenceCache"
+ extends="com.google.inject.util.AbstractReferenceCache"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ReferenceCache"
+ type="com.google.inject.util.ReferenceCache"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyReferenceType" type="com.google.inject.util.ReferenceType">
+</parameter>
+<parameter name="valueReferenceType" type="com.google.inject.util.ReferenceType">
+</parameter>
+</constructor>
+<constructor name="ReferenceCache"
+ type="com.google.inject.util.ReferenceCache"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="create"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="K">
+</parameter>
+</method>
+<method name="of"
+ return="com.google.inject.util.ReferenceCache&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyReferenceType" type="com.google.inject.util.ReferenceType">
+</parameter>
+<parameter name="valueReferenceType" type="com.google.inject.util.ReferenceType">
+</parameter>
+<parameter name="function" type="com.google.inject.util.Function&lt;? super K, ? extends V&gt;">
+</parameter>
+</method>
+</class>
+<class name="ReferenceMap"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ReferenceMap"
+ type="com.google.inject.util.ReferenceMap"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyReferenceType" type="com.google.inject.util.ReferenceType">
+</parameter>
+<parameter name="valueReferenceType" type="com.google.inject.util.ReferenceType">
+</parameter>
+</constructor>
+<method name="clear"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="containsKey"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.Object">
+</parameter>
+</method>
+<method name="containsValue"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="entrySet"
+ return="java.util.Set&lt;java.util.Map.Entry&lt;K, V&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="get"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.Object">
+</parameter>
+</method>
+<method name="getPutStrategy"
+ return="com.google.inject.util.ReferenceMap.PutStrategy"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="isEmpty"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="keySet"
+ return="java.util.Set&lt;K&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="put"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="K">
+</parameter>
+<parameter name="value" type="V">
+</parameter>
+</method>
+<method name="putAll"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="java.util.Map&lt;? extends K, ? extends V&gt;">
+</parameter>
+</method>
+<method name="putIfAbsent"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="K">
+</parameter>
+<parameter name="value" type="V">
+</parameter>
+</method>
+<method name="putIfAbsentStrategy"
+ return="com.google.inject.util.ReferenceMap.Strategy"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="putStrategy"
+ return="com.google.inject.util.ReferenceMap.Strategy"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="remove"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.Object">
+</parameter>
+</method>
+<method name="remove"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.Object">
+</parameter>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="replace"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="K">
+</parameter>
+<parameter name="oldValue" type="V">
+</parameter>
+<parameter name="newValue" type="V">
+</parameter>
+</method>
+<method name="replace"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="K">
+</parameter>
+<parameter name="value" type="V">
+</parameter>
+</method>
+<method name="replaceStrategy"
+ return="com.google.inject.util.ReferenceMap.Strategy"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="size"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="values"
+ return="java.util.Collection&lt;V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ReferenceMap.PutStrategy"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="com.google.inject.util.ReferenceMap.Strategy">
+</implements>
+<method name="valueOf"
+ return="com.google.inject.util.ReferenceMap.PutStrategy"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.util.ReferenceMap.PutStrategy[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="ReferenceMap.Strategy"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<method name="execute"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="map" type="com.google.inject.util.ReferenceMap">
+</parameter>
+<parameter name="keyReference" type="java.lang.Object">
+</parameter>
+<parameter name="valueReference" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="ReferenceType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.util.ReferenceType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.util.ReferenceType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="StackTraceElements"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="StackTraceElements"
+ type="com.google.inject.util.StackTraceElements"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="forMember"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="forType"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<class name="Stopwatch"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Stopwatch"
+ type="com.google.inject.util.Stopwatch"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="reset"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="resetAndLog"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="logger" type="java.util.logging.Logger">
+</parameter>
+<parameter name="label" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="Strings"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Strings"
+ type="com.google.inject.util.Strings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="capitalize"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="s" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="ToStringBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ToStringBuilder"
+ type="com.google.inject.util.ToStringBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="ToStringBuilder"
+ type="com.google.inject.util.ToStringBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class">
+</parameter>
+</constructor>
+<method name="add"
+ return="com.google.inject.util.ToStringBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+</package>
+</api>
diff --git a/lib/build/guice-2.0.xml b/lib/build/guice-2.0.xml
new file mode 100644
index 0000000..d71b65c
--- /dev/null
+++ b/lib/build/guice-2.0.xml
@@ -0,0 +1,6683 @@
+<api>
+<package name="com.google.inject"
+>
+<class name="AbstractModule"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Module">
+</implements>
+<constructor name="AbstractModule"
+ type="com.google.inject.AbstractModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="clazz" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="binder"
+ return="com.google.inject.Binder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="builder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<interface name="Binder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="newPrivateBinder"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="skipSources"
+ return="com.google.inject.Binder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classesToSkip" type="java.lang.Class...">
+</parameter>
+</method>
+<method name="withSource"
+ return="com.google.inject.Binder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<interface name="Binding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptScopingVisitor"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;">
+</parameter>
+</method>
+<method name="acceptTargetVisitor"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;? super T, V&gt;">
+</parameter>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="BindingAnnotation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ConfigurationException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ConfigurationException"
+ type="com.google.inject.ConfigurationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPartialValue"
+ return="E"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="withPartialValue"
+ return="com.google.inject.ConfigurationException"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="partialValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="CreationException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CreationException"
+ type="com.google.inject.CreationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.util.Collection&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Exposed"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Guice"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+</class>
+<class name="ImplementedBy"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Inject"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="Injector"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createChildInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createChildInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="findBindingsByType"
+ return="java.util.List&lt;com.google.inject.Binding&lt;T&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBindings"
+ return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getParent"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="injectMembers"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="Key"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</constructor>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</constructor>
+<method name="equals"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="getAnnotation"
+ return="java.lang.annotation.Annotation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAnnotationType"
+ return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hashCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="MembersInjector"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="injectMembers"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+</interface>
+<interface name="Module"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+</interface>
+<class name="OutOfScopeException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+</class>
+<interface name="PrivateBinder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binder">
+</implements>
+<method name="expose"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="skipSources"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classesToSkip" type="java.lang.Class...">
+</parameter>
+</method>
+<method name="withSource"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="PrivateModule"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Module">
+</implements>
+<constructor name="PrivateModule"
+ type="com.google.inject.PrivateModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="clazz" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="binder"
+ return="com.google.inject.PrivateBinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="expose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<class name="ProvidedBy"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="Provider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Provides"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ProvisionException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="Scope"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="scope"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+<parameter name="unscoped" type="com.google.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="ScopeAnnotation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Scopes"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="NO_SCOPE"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SINGLETON"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Singleton"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Stage"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.Stage[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="TypeLiteral"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="TypeLiteral"
+ type="com.google.inject.TypeLiteral"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<method name="equals"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="getExceptionTypes"
+ return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodOrConstructor" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getFieldType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="field" type="java.lang.reflect.Field">
+</parameter>
+</method>
+<method name="getParameterTypes"
+ return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodOrConstructor" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getRawType"
+ return="java.lang.Class&lt;? super T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getReturnType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</method>
+<method name="getSupertype"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="supertype" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getType"
+ return="java.lang.reflect.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hashCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
+<package name="com.google.inject.assistedinject"
+>
+<class name="Assisted"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="AssistedInject"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="FactoryProvider"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<implements name="com.google.inject.Provider">
+</implements>
+<method name="get"
+ return="F"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newFactory"
+ return="com.google.inject.Provider&lt;F&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryType" type="com.google.inject.TypeLiteral&lt;F&gt;">
+</parameter>
+<parameter name="implementationType" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="newFactory"
+ return="com.google.inject.Provider&lt;F&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryType" type="java.lang.Class&lt;F&gt;">
+</parameter>
+<parameter name="implementationType" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.binder"
+>
+<interface name="AnnotatedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.binder.LinkedBindingBuilder">
+</implements>
+<method name="annotatedWith"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="AnnotatedConstantBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="com.google.inject.binder.ConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.binder.ConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="AnnotatedElementBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="ConstantBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="E">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="char">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="double">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="float">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="long">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="short">
+</parameter>
+</method>
+</interface>
+<interface name="LinkedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.binder.ScopedBindingBuilder">
+</implements>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetKey" type="com.google.inject.Key&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="toInstance"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerKey" type="com.google.inject.Key&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="com.google.inject.Provider&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerType" type="java.lang.Class&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ScopedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="asEagerSingleton"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="in"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="in"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</interface>
+</package>
+<package name="com.google.inject.jndi"
+>
+<class name="JndiIntegration"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="fromJndi"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.matcher"
+>
+<class name="AbstractMatcher"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.matcher.Matcher">
+</implements>
+<constructor name="AbstractMatcher"
+ type="com.google.inject.matcher.AbstractMatcher"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="and"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="or"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+</class>
+<interface name="Matcher"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="and"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="matches"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="T">
+</parameter>
+</method>
+<method name="or"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+</interface>
+<class name="Matchers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="any"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="identicalTo"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="inPackage"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackage" type="java.lang.Package">
+</parameter>
+</method>
+<method name="inSubpackage"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackageName" type="java.lang.String">
+</parameter>
+</method>
+<method name="not"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="only"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="returns"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.Method&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="returnType" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+</method>
+<method name="subclassesOf"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="superclass" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.multibindings"
+>
+<class name="MapBinder"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addBinding"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="K">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</class>
+<class name="Multibinder"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addBinding"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.name"
+>
+<class name="Named"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Names"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="properties" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="bindProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="properties" type="java.util.Properties">
+</parameter>
+</method>
+<method name="named"
+ return="com.google.inject.name.Named"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.servlet"
+>
+<class name="GuiceFilter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceFilter"
+ type="com.google.inject.servlet.GuiceFilter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="doFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletRequest" type="ServletRequest">
+</parameter>
+<parameter name="servletResponse" type="ServletResponse">
+</parameter>
+<parameter name="filterChain" type="FilterChain">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterConfig" type="FilterConfig">
+</parameter>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+</class>
+<class name="GuiceServletContextListener"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceServletContextListener"
+ type="com.google.inject.servlet.GuiceServletContextListener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="contextDestroyed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletContextEvent" type="ServletContextEvent">
+</parameter>
+</method>
+<method name="contextInitialized"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletContextEvent" type="ServletContextEvent">
+</parameter>
+</method>
+<method name="getInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<class name="RequestParameters"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="RequestScoped"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ServletModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ServletModule"
+ type="com.google.inject.servlet.ServletModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configureServlets"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="filter"
+ return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="urlPattern" type="java.lang.String">
+</parameter>
+<parameter name="morePatterns" type="java.lang.String...">
+</parameter>
+</method>
+<method name="filterRegex"
+ return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="regex" type="java.lang.String">
+</parameter>
+<parameter name="regexes" type="java.lang.String...">
+</parameter>
+</method>
+<method name="serve"
+ return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="urlPattern" type="java.lang.String">
+</parameter>
+<parameter name="morePatterns" type="java.lang.String...">
+</parameter>
+</method>
+<method name="serveRegex"
+ return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="regex" type="java.lang.String">
+</parameter>
+<parameter name="regexes" type="java.lang.String...">
+</parameter>
+</method>
+</class>
+<interface name="ServletModule.FilterKeyBindingBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dummyFilterClass" type="com.google.inject.Key&lt;? extends Filter&gt;">
+</parameter>
+<parameter name="contextParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dummyFilterClass" type="java.lang.Class&lt;? extends Filter&gt;">
+</parameter>
+<parameter name="contextParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ServletModule.ServletKeyBindingBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;">
+</parameter>
+<parameter name="contextParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;">
+</parameter>
+<parameter name="contextParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+</interface>
+<class name="ServletScopes"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="REQUEST"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SESSION"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SessionScoped"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+</package>
+<package name="com.google.inject.spi"
+>
+<interface name="BindingScopingVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visitEagerSingleton"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitNoScoping"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitScope"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="visitScopeAnnotation"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="BindingTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ConstructorBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getConstructor"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInjectableMembers"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMethodInterceptors"
+ return="java.util.Map&lt;java.lang.reflect.Method, java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ConvertedConstantBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSourceKey"
+ return="com.google.inject.Key&lt;java.lang.String&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValue"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="DefaultBindingScopingVisitor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingScopingVisitor">
+</implements>
+<constructor name="DefaultBindingScopingVisitor"
+ type="com.google.inject.spi.DefaultBindingScopingVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visitEagerSingleton"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitNoScoping"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="visitScope"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="visitScopeAnnotation"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</class>
+<class name="DefaultBindingTargetVisitor"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<constructor name="DefaultBindingTargetVisitor"
+ type="com.google.inject.spi.DefaultBindingTargetVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructorBinding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="convertedConstantBinding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="exposedBinding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instanceBinding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="linkedKeyBinding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerBinding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerInstanceBinding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerKeyBinding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="untargettedBinding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;? extends T&gt;">
+</parameter>
+</method>
+</class>
+<class name="DefaultElementVisitor"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.ElementVisitor">
+</implements>
+<constructor name="DefaultElementVisitor"
+ type="com.google.inject.spi.DefaultElementVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectionRequest" type="com.google.inject.spi.InjectionRequest">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interceptorBinding" type="com.google.inject.spi.InterceptorBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="privateElements" type="com.google.inject.spi.PrivateElements">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerLookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeBinding" type="com.google.inject.spi.ScopeBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="staticInjectionRequest" type="com.google.inject.spi.StaticInjectionRequest">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeConverterBinding" type="com.google.inject.spi.TypeConverterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeListenerBinding">
+</parameter>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="element" type="com.google.inject.spi.Element">
+</parameter>
+</method>
+</class>
+<class name="Dependency"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="forInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectionPoints" type="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.spi.Dependency&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInjectionPoint"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getParameterIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isNullable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="Element"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="acceptVisitor"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ElementVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="request" type="com.google.inject.spi.InjectionRequest">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InterceptorBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elements" type="com.google.inject.spi.PrivateElements">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ScopeBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="request" type="com.google.inject.spi.StaticInjectionRequest">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeConverterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeListenerBinding">
+</parameter>
+</method>
+</interface>
+<class name="Elements"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Elements"
+ type="com.google.inject.spi.Elements"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="getModule"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elements" type="java.lang.Iterable&lt;? extends com.google.inject.spi.Element&gt;">
+</parameter>
+</method>
+</class>
+<interface name="ExposedBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="applyTo"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getPrivateElements"
+ return="com.google.inject.spi.PrivateElements"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="HasDependencies"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="InjectionListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="afterInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectee" type="I">
+</parameter>
+</method>
+</interface>
+<class name="InjectionPoint"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="forConstructorOf"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="forConstructorOf"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="forInstanceMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="forInstanceMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="forStaticMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral">
+</parameter>
+</method>
+<method name="forStaticMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getDependencies"
+ return="java.util.List&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMember"
+ return="java.lang.reflect.Member"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isOptional"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="InjectionRequest"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="InjectionRequest"
+ type="com.google.inject.spi.InjectionRequest"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="instance" type="T">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="R"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;R&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="ConfigurationException" type="com.google.inject.ConfigurationException">
+</exception>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="InstanceBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="InterceptorBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getClassMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInterceptors"
+ return="java.util.List&lt;MethodInterceptor&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMethodMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="LinkedKeyBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getLinkedKey"
+ return="com.google.inject.Key&lt;? extends T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="MembersInjectorLookup"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="MembersInjectorLookup"
+ type="com.google.inject.spi.MembersInjectorLookup"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getDelegate"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initializeDelegate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delegate" type="com.google.inject.MembersInjector&lt;T&gt;">
+</parameter>
+</method>
+</class>
+<class name="Message"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sources" type="java.util.List&lt;java.lang.Object&gt;">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getCause"
+ return="java.lang.Throwable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessage"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSources"
+ return="java.util.List&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="PrivateElements"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExposedKeys"
+ return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExposedSource"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getProvidedKey"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderInstanceBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProviderInstance"
+ return="com.google.inject.Provider&lt;? extends T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderKeyBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getProviderKey"
+ return="com.google.inject.Key&lt;? extends com.google.inject.Provider&lt;? extends T&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="ProviderLookup"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="ProviderLookup"
+ type="com.google.inject.spi.ProviderLookup"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getDelegate"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initializeDelegate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delegate" type="com.google.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+</class>
+<interface name="ProviderWithDependencies"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<implements name="com.google.inject.Provider">
+</implements>
+</interface>
+<class name="ScopeBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getAnnotationType"
+ return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getScope"
+ return="com.google.inject.Scope"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="StaticInjectionRequest"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="ConfigurationException" type="com.google.inject.ConfigurationException">
+</exception>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="java.lang.Class&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="TypeConverter"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="convert"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+<parameter name="toType" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+</interface>
+<class name="TypeConverterBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeConverter"
+ return="com.google.inject.spi.TypeConverter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="TypeEncounter"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="register"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="membersInjector" type="com.google.inject.MembersInjector&lt;? super I&gt;">
+</parameter>
+</method>
+<method name="register"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="com.google.inject.spi.InjectionListener&lt;? super I&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="TypeListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="hear"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;I&gt;">
+</parameter>
+<parameter name="encounter" type="com.google.inject.spi.TypeEncounter&lt;I&gt;">
+</parameter>
+</method>
+</interface>
+<class name="TypeListenerBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getListener"
+ return="com.google.inject.spi.TypeListener"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="UntargettedBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+</interface>
+</package>
+<package name="com.google.inject.spring"
+>
+<class name="SpringIntegration"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindAll"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="beanFactory" type="ListableBeanFactory">
+</parameter>
+</method>
+<method name="fromSpring"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.throwingproviders"
+>
+<interface name="ThrowingProvider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+</interface>
+<class name="ThrowingProviderBinder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bind"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceType" type="java.lang.Class&lt;P&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="create"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+</class>
+<class name="ThrowingProviderBinder.SecondaryBinder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ThrowingProviderBinder.SecondaryBinder"
+ type="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceType" type="java.lang.Class&lt;P&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.reflect.Type">
+</parameter>
+</constructor>
+<method name="annotatedWith"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="P">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetKey" type="com.google.inject.Key&lt;? extends P&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetType" type="java.lang.Class&lt;? extends P&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.tools.jmx"
+>
+<interface name="ManagedBindingMBean"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getKey"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Manager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Manager"
+ type="com.google.inject.tools.jmx.Manager"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="main"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+<method name="manage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="domain" type="java.lang.String">
+</parameter>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+<method name="manage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="server" type="javax.management.MBeanServer">
+</parameter>
+<parameter name="domain" type="java.lang.String">
+</parameter>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.util"
+>
+<class name="Modules"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="combine"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="combine"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="override"
+ return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="override"
+ return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<field name="EMPTY_MODULE"
+ type="com.google.inject.Module"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="Modules.OverriddenModuleBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="with"
+ return="com.google.inject.Module"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overrides" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="with"
+ return="com.google.inject.Module"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overrides" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+</interface>
+<class name="Providers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="of"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+</class>
+<class name="Types"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="arrayOf"
+ return="java.lang.reflect.GenericArrayType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="componentType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="listOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elementType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="mapOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="valueType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="newParameterizedType"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rawType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="typeArguments" type="java.lang.reflect.Type...">
+</parameter>
+</method>
+<method name="newParameterizedTypeWithOwner"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ownerType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="rawType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="typeArguments" type="java.lang.reflect.Type...">
+</parameter>
+</method>
+<method name="providerOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providedType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="setOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elementType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="subtypeOf"
+ return="java.lang.reflect.WildcardType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bound" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="supertypeOf"
+ return="java.lang.reflect.WildcardType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bound" type="java.lang.reflect.Type">
+</parameter>
+</method>
+</class>
+</package>
+</api>
diff --git a/lib/build/guice-3.0.xml b/lib/build/guice-3.0.xml
new file mode 100644
index 0000000..044b615
--- /dev/null
+++ b/lib/build/guice-3.0.xml
@@ -0,0 +1,10840 @@
+<api>
+<package name="com.google.inject"
+>
+<class name="AbstractModule"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Module">
+</implements>
+<constructor name="AbstractModule"
+ type="com.google.inject.AbstractModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="clazz" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="binder"
+ return="com.google.inject.Binder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="builder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<interface name="Binder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="disableCircularProxies"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="newPrivateBinder"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="requireExplicitBindings"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="skipSources"
+ return="com.google.inject.Binder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classesToSkip" type="java.lang.Class...">
+</parameter>
+</method>
+<method name="withSource"
+ return="com.google.inject.Binder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<interface name="Binding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptScopingVisitor"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;">
+</parameter>
+</method>
+<method name="acceptTargetVisitor"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;? super T, V&gt;">
+</parameter>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="BindingAnnotation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ConfigurationException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ConfigurationException"
+ type="com.google.inject.ConfigurationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPartialValue"
+ return="E"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="withPartialValue"
+ return="com.google.inject.ConfigurationException"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="partialValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="CreationException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CreationException"
+ type="com.google.inject.CreationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.util.Collection&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Exposed"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Guice"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+</class>
+<class name="ImplementedBy"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Inject"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="Injector"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createChildInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createChildInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="findBindingsByType"
+ return="java.util.List&lt;com.google.inject.Binding&lt;T&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getAllBindings"
+ return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBindings"
+ return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExistingBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getParent"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getScopeBindings"
+ return="java.util.Map&lt;java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;, com.google.inject.Scope&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeConverterBindings"
+ return="java.util.Set&lt;com.google.inject.spi.TypeConverterBinding&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="injectMembers"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="Key"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</constructor>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</constructor>
+<method name="equals"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="getAnnotation"
+ return="java.lang.annotation.Annotation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAnnotationType"
+ return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasAttributes"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hashCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="ofType"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="ofType"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="ofType"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="withoutAttributes"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="MembersInjector"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="injectMembers"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+</interface>
+<interface name="Module"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+</interface>
+<class name="OutOfScopeException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+</class>
+<interface name="PrivateBinder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binder">
+</implements>
+<method name="expose"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="skipSources"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classesToSkip" type="java.lang.Class...">
+</parameter>
+</method>
+<method name="withSource"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="PrivateModule"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Module">
+</implements>
+<constructor name="PrivateModule"
+ type="com.google.inject.PrivateModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="clazz" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="binder"
+ return="com.google.inject.PrivateBinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="expose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<class name="ProvidedBy"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="Provider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="javax.inject.Provider">
+</implements>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Provides"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ProvisionException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="Scope"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="scope"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+<parameter name="unscoped" type="com.google.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="ScopeAnnotation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Scopes"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="isSingleton"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+</method>
+<field name="NO_SCOPE"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SINGLETON"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Singleton"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Stage"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.Stage[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="TypeLiteral"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="TypeLiteral"
+ type="com.google.inject.TypeLiteral"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<method name="equals"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="getExceptionTypes"
+ return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodOrConstructor" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getFieldType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="field" type="java.lang.reflect.Field">
+</parameter>
+</method>
+<method name="getParameterTypes"
+ return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodOrConstructor" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getRawType"
+ return="java.lang.Class&lt;? super T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getReturnType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</method>
+<method name="getSupertype"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="supertype" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getType"
+ return="java.lang.reflect.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hashCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
+<package name="com.google.inject.assistedinject"
+>
+<class name="Assisted"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="AssistedInject"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="AssistedInjectBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getAssistedMethods"
+ return="java.util.Collection&lt;com.google.inject.assistedinject.AssistedMethod&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="AssistedInjectTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="assistedInjectBinding" type="com.google.inject.assistedinject.AssistedInjectBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="AssistedMethod"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFactoryMethod"
+ return="java.lang.reflect.Method"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getImplementationConstructor"
+ return="java.lang.reflect.Constructor&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getImplementationType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="FactoryModuleBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FactoryModuleBuilder"
+ type="com.google.inject.assistedinject.FactoryModuleBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="build"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryInterface" type="com.google.inject.Key&lt;F&gt;">
+</parameter>
+</method>
+<method name="build"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryInterface" type="com.google.inject.TypeLiteral&lt;F&gt;">
+</parameter>
+</method>
+<method name="build"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryInterface" type="java.lang.Class&lt;F&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+</class>
+<class name="FactoryProvider"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<implements name="com.google.inject.Provider">
+</implements>
+<method name="get"
+ return="F"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newFactory"
+ return="com.google.inject.Provider&lt;F&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryType" type="com.google.inject.TypeLiteral&lt;F&gt;">
+</parameter>
+<parameter name="implementationType" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="newFactory"
+ return="com.google.inject.Provider&lt;F&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryType" type="java.lang.Class&lt;F&gt;">
+</parameter>
+<parameter name="implementationType" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.binder"
+>
+<interface name="AnnotatedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.binder.LinkedBindingBuilder">
+</implements>
+<method name="annotatedWith"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="AnnotatedConstantBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="com.google.inject.binder.ConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.binder.ConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="AnnotatedElementBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="ConstantBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="E">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="byte">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="char">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="double">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="float">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="long">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="short">
+</parameter>
+</method>
+</interface>
+<interface name="LinkedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.binder.ScopedBindingBuilder">
+</implements>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetKey" type="com.google.inject.Key&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="toConstructor"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructor" type="java.lang.reflect.Constructor&lt;S&gt;">
+</parameter>
+</method>
+<method name="toConstructor"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructor" type="java.lang.reflect.Constructor&lt;S&gt;">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;? extends S&gt;">
+</parameter>
+</method>
+<method name="toInstance"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerKey" type="com.google.inject.Key&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="com.google.inject.Provider&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerType" type="com.google.inject.TypeLiteral&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerType" type="java.lang.Class&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ScopedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="asEagerSingleton"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="in"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="in"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</interface>
+</package>
+<package name="com.google.inject.grapher"
+>
+<interface name="BindingEdge"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="setType"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.grapher.BindingEdge.Type">
+</parameter>
+</method>
+</interface>
+<interface name="BindingEdge.Factory"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="newBindingEdge"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="K">
+</parameter>
+<parameter name="toId" type="K">
+</parameter>
+</method>
+</interface>
+<class name="BindingEdge.Type"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.BindingEdge.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.BindingEdge.Type[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="DependencyEdge"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</interface>
+<interface name="DependencyEdge.Factory"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="newDependencyEdge"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="K">
+</parameter>
+<parameter name="fromPoint" type="com.google.inject.spi.InjectionPoint">
+</parameter>
+<parameter name="toId" type="K">
+</parameter>
+</method>
+</interface>
+<class name="GrapherModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GrapherModule"
+ type="com.google.inject.grapher.GrapherModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<class name="GraphingVisitor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<constructor name="GraphingVisitor"
+ type="com.google.inject.grapher.GraphingVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="idFactory" type="com.google.inject.grapher.NodeIdFactory&lt;K&gt;">
+</parameter>
+<parameter name="interfaceNodeFactory" type="com.google.inject.grapher.InterfaceNode.Factory&lt;K, N&gt;">
+</parameter>
+<parameter name="implementationNodeFactory" type="com.google.inject.grapher.ImplementationNode.Factory&lt;K, M&gt;">
+</parameter>
+<parameter name="bindingEdgeFactory" type="com.google.inject.grapher.BindingEdge.Factory&lt;K, B&gt;">
+</parameter>
+<parameter name="dependencyEdgeFactory" type="com.google.inject.grapher.DependencyEdge.Factory&lt;K, D&gt;">
+</parameter>
+<parameter name="nodeAliasFactory" type="com.google.inject.grapher.NodeAliasFactory&lt;K&gt;">
+</parameter>
+</constructor>
+<method name="getClassNodeId"
+ return="K"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+</method>
+<method name="getInstanceNodeId"
+ return="K"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+</method>
+<method name="newBindingEdge"
+ return="B"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="nodeId" type="K">
+</parameter>
+<parameter name="toId" type="K">
+</parameter>
+<parameter name="type" type="com.google.inject.grapher.BindingEdge.Type">
+</parameter>
+</method>
+<method name="newClassImplementationNode"
+ return="M"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+<parameter name="constructorInjectionPoint" type="com.google.inject.spi.InjectionPoint">
+</parameter>
+<parameter name="memberInjectionPoints" type="java.util.Collection&lt;com.google.inject.spi.InjectionPoint&gt;">
+</parameter>
+</method>
+<method name="newDependencyEdge"
+ return="D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="nodeId" type="K">
+</parameter>
+<parameter name="injectionPoint" type="com.google.inject.spi.InjectionPoint">
+</parameter>
+<parameter name="dependency" type="com.google.inject.spi.Dependency&lt;?&gt;">
+</parameter>
+</method>
+<method name="newDependencyEdges"
+ return="java.util.Collection&lt;D&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="nodeId" type="K">
+</parameter>
+<parameter name="node" type="M">
+</parameter>
+<parameter name="dependencies" type="java.util.Collection&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;">
+</parameter>
+</method>
+<method name="newInstanceImplementationNode"
+ return="M"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="newInterfaceNode"
+ return="N"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConstructorBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ExposedBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InstanceBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.lang.Void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.UntargettedBinding&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<interface name="ImplementationNode"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addMember"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="setClassKey"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="setInstance"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="setSource"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<interface name="ImplementationNode.Factory"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="newImplementationNode"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nodeId" type="K">
+</parameter>
+</method>
+</interface>
+<class name="InjectorGrapher"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="InjectorGrapher"
+ type="com.google.inject.grapher.InjectorGrapher"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyVisitor" type="com.google.inject.spi.BindingTargetVisitor&lt;java.lang.Object, java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;&gt;">
+</parameter>
+<parameter name="graphingVisitor" type="com.google.inject.spi.BindingTargetVisitor&lt;java.lang.Object, java.lang.Void&gt;">
+</parameter>
+<parameter name="renderer" type="com.google.inject.grapher.Renderer">
+</parameter>
+</constructor>
+<method name="graph"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="of"
+ return="com.google.inject.grapher.InjectorGrapher"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+<method name="rootedAt"
+ return="com.google.inject.grapher.InjectorGrapher"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keys" type="com.google.inject.Key&lt;?&gt;...">
+</parameter>
+</method>
+<method name="rootedAt"
+ return="com.google.inject.grapher.InjectorGrapher"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classes" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+</class>
+<interface name="InterfaceNode"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="setKey"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="setSource"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<interface name="InterfaceNode.Factory"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="newInterfaceNode"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nodeId" type="K">
+</parameter>
+</method>
+</interface>
+<interface name="NameFactory"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getAnnotationName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getClassName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getInstanceName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="getMemberName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getSourceName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<interface name="NodeAliasFactory"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="newAlias"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="K">
+</parameter>
+<parameter name="toId" type="K">
+</parameter>
+</method>
+</interface>
+<interface name="NodeIdFactory"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getClassNodeId"
+ return="K"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getInstanceNodeId"
+ return="K"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="Renderer"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="render"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</interface>
+<class name="ShortNameFactory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.NameFactory">
+</implements>
+<constructor name="ShortNameFactory"
+ type="com.google.inject.grapher.ShortNameFactory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getAnnotationName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getClassName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getFileString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="stackTraceElement" type="java.lang.StackTraceElement">
+</parameter>
+</method>
+<method name="getInstanceName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="getMemberName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getMethodString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</method>
+<method name="getSourceName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="StringNodeIdFactory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.NodeIdFactory">
+</implements>
+<constructor name="StringNodeIdFactory"
+ type="com.google.inject.grapher.StringNodeIdFactory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getClassNodeId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getInstanceNodeId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<class name="TransitiveDependencyVisitor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<constructor name="TransitiveDependencyVisitor"
+ type="com.google.inject.grapher.TransitiveDependencyVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConstructorBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ExposedBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InstanceBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.UntargettedBinding&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.grapher.graphviz"
+>
+<class name="ArrowType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.ArrowType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.ArrowType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="BindingEdgeFactory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.BindingEdge.Factory">
+</implements>
+<constructor name="BindingEdgeFactory"
+ type="com.google.inject.grapher.graphviz.BindingEdgeFactory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="renderer" type="com.google.inject.grapher.graphviz.GraphvizRenderer">
+</parameter>
+</constructor>
+<method name="newAdaptor"
+ return="com.google.inject.grapher.graphviz.BindingEdgeFactory.GraphvizEdgeAdaptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</method>
+<method name="newBindingEdge"
+ return="com.google.inject.grapher.BindingEdge&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="java.lang.String">
+</parameter>
+<parameter name="toId" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="BindingEdgeFactory.GraphvizEdgeAdaptor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="com.google.inject.grapher.BindingEdge">
+</implements>
+<constructor name="BindingEdgeFactory.GraphvizEdgeAdaptor"
+ type="com.google.inject.grapher.graphviz.BindingEdgeFactory.GraphvizEdgeAdaptor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</constructor>
+<method name="setType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.grapher.BindingEdge.Type">
+</parameter>
+</method>
+<field name="edge"
+ type="com.google.inject.grapher.graphviz.GraphvizEdge"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="CompassPoint"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.CompassPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.CompassPoint[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="DependencyEdgeFactory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.DependencyEdge.Factory">
+</implements>
+<constructor name="DependencyEdgeFactory"
+ type="com.google.inject.grapher.graphviz.DependencyEdgeFactory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="renderer" type="com.google.inject.grapher.graphviz.GraphvizRenderer">
+</parameter>
+<parameter name="portIdFactory" type="com.google.inject.grapher.graphviz.PortIdFactory">
+</parameter>
+</constructor>
+<method name="newAdaptor"
+ return="com.google.inject.grapher.graphviz.DependencyEdgeFactory.GraphvizEdgeAdaptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</method>
+<method name="newDependencyEdge"
+ return="com.google.inject.grapher.DependencyEdge&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="java.lang.String">
+</parameter>
+<parameter name="fromPoint" type="com.google.inject.spi.InjectionPoint">
+</parameter>
+<parameter name="toId" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="DependencyEdgeFactory.GraphvizEdgeAdaptor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="com.google.inject.grapher.DependencyEdge">
+</implements>
+<constructor name="DependencyEdgeFactory.GraphvizEdgeAdaptor"
+ type="com.google.inject.grapher.graphviz.DependencyEdgeFactory.GraphvizEdgeAdaptor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</constructor>
+<field name="edge"
+ type="com.google.inject.grapher.graphviz.GraphvizEdge"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="EdgeStyle"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.EdgeStyle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.EdgeStyle[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="GraphvizEdge"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GraphvizEdge"
+ type="com.google.inject.grapher.graphviz.GraphvizEdge"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tailNodeId" type="java.lang.String">
+</parameter>
+<parameter name="headNodeId" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="getArrowHead"
+ return="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getArrowTail"
+ return="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeadCompassPoint"
+ return="com.google.inject.grapher.graphviz.CompassPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeadNodeId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeadPortId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStyle"
+ return="com.google.inject.grapher.graphviz.EdgeStyle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTailCompassPoint"
+ return="com.google.inject.grapher.graphviz.CompassPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTailNodeId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTailPortId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setArrowHead"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="arrowHead" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;">
+</parameter>
+</method>
+<method name="setArrowTail"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="arrowTail" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;">
+</parameter>
+</method>
+<method name="setHeadCompassPoint"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="headCompassPoint" type="com.google.inject.grapher.graphviz.CompassPoint">
+</parameter>
+</method>
+<method name="setHeadPortId"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="headPortId" type="java.lang.String">
+</parameter>
+</method>
+<method name="setStyle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="style" type="com.google.inject.grapher.graphviz.EdgeStyle">
+</parameter>
+</method>
+<method name="setTailCompassPoint"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tailCompassPoint" type="com.google.inject.grapher.graphviz.CompassPoint">
+</parameter>
+</method>
+<method name="setTailPortId"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tailPortId" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="GraphvizModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GraphvizModule"
+ type="com.google.inject.grapher.graphviz.GraphvizModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<class name="GraphvizNode"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GraphvizNode"
+ type="com.google.inject.grapher.graphviz.GraphvizNode"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nodeId" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="addField"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="portId" type="java.lang.String">
+</parameter>
+<parameter name="title" type="java.lang.String">
+</parameter>
+</method>
+<method name="addSubtitle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+<parameter name="subtitle" type="java.lang.String">
+</parameter>
+</method>
+<method name="getFields"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeaderBackgroundColor"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeaderTextColor"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNodeId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getShape"
+ return="com.google.inject.grapher.graphviz.NodeShape"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStyle"
+ return="com.google.inject.grapher.graphviz.NodeStyle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubtitles"
+ return="java.util.List&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTitle"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setHeaderBackgroundColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="headerBackgroundColor" type="java.lang.String">
+</parameter>
+</method>
+<method name="setHeaderTextColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="headerTextColor" type="java.lang.String">
+</parameter>
+</method>
+<method name="setShape"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shape" type="com.google.inject.grapher.graphviz.NodeShape">
+</parameter>
+</method>
+<method name="setStyle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="style" type="com.google.inject.grapher.graphviz.NodeStyle">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="GraphvizRenderer"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.NodeAliasFactory">
+</implements>
+<implements name="com.google.inject.grapher.Renderer">
+</implements>
+<constructor name="GraphvizRenderer"
+ type="com.google.inject.grapher.graphviz.GraphvizRenderer"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addEdge"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</method>
+<method name="addNode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</method>
+<method name="finish"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getArrowString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="arrows" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;">
+</parameter>
+</method>
+<method name="getEdgeAttributes"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</method>
+<method name="getEdgeEndPoint"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="nodeId" type="java.lang.String">
+</parameter>
+<parameter name="portId" type="java.lang.String">
+</parameter>
+<parameter name="compassPoint" type="com.google.inject.grapher.graphviz.CompassPoint">
+</parameter>
+</method>
+<method name="getGraphAttributes"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getNodeAttributes"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</method>
+<method name="getNodeLabel"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</method>
+<method name="htmlEscape"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="str" type="java.lang.String">
+</parameter>
+</method>
+<method name="newAlias"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="java.lang.String">
+</parameter>
+<parameter name="toId" type="java.lang.String">
+</parameter>
+</method>
+<method name="render"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="renderEdge"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</method>
+<method name="renderNode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</method>
+<method name="resolveAlias"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="id" type="java.lang.String">
+</parameter>
+</method>
+<method name="setOut"
+ return="com.google.inject.grapher.graphviz.GraphvizRenderer"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="java.io.PrintWriter">
+</parameter>
+</method>
+<method name="setRankdir"
+ return="com.google.inject.grapher.graphviz.GraphvizRenderer"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rankdir" type="java.lang.String">
+</parameter>
+</method>
+<method name="start"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<class name="ImplementationNodeFactory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.ImplementationNode.Factory">
+</implements>
+<constructor name="ImplementationNodeFactory"
+ type="com.google.inject.grapher.graphviz.ImplementationNodeFactory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="renderer" type="com.google.inject.grapher.graphviz.GraphvizRenderer">
+</parameter>
+<parameter name="nameFactory" type="com.google.inject.grapher.NameFactory">
+</parameter>
+<parameter name="portIdFactory" type="com.google.inject.grapher.graphviz.PortIdFactory">
+</parameter>
+</constructor>
+<method name="newAdaptor"
+ return="com.google.inject.grapher.graphviz.ImplementationNodeFactory.GraphvizNodeAdaptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</method>
+<method name="newImplementationNode"
+ return="com.google.inject.grapher.ImplementationNode&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nodeId" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="ImplementationNodeFactory.GraphvizNodeAdaptor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="com.google.inject.grapher.ImplementationNode">
+</implements>
+<constructor name="ImplementationNodeFactory.GraphvizNodeAdaptor"
+ type="com.google.inject.grapher.graphviz.ImplementationNodeFactory.GraphvizNodeAdaptor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</constructor>
+<method name="addMember"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="setClassKey"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="setInstance"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="setSource"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+<field name="node"
+ type="com.google.inject.grapher.graphviz.GraphvizNode"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="InterfaceNodeFactory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.InterfaceNode.Factory">
+</implements>
+<constructor name="InterfaceNodeFactory"
+ type="com.google.inject.grapher.graphviz.InterfaceNodeFactory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="renderer" type="com.google.inject.grapher.graphviz.GraphvizRenderer">
+</parameter>
+<parameter name="nameFactory" type="com.google.inject.grapher.NameFactory">
+</parameter>
+</constructor>
+<method name="newInterfaceNode"
+ return="com.google.inject.grapher.InterfaceNode&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nodeId" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="InterfaceNodeFactory.GraphvizNodeAdaptor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="com.google.inject.grapher.InterfaceNode">
+</implements>
+<constructor name="InterfaceNodeFactory.GraphvizNodeAdaptor"
+ type="com.google.inject.grapher.graphviz.InterfaceNodeFactory.GraphvizNodeAdaptor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</constructor>
+<method name="setKey"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="setSource"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+<field name="node"
+ type="com.google.inject.grapher.graphviz.GraphvizNode"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="NodeShape"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.NodeShape"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.NodeShape[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="NodeStyle"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.NodeStyle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.NodeStyle[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="PortIdFactory"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getPortId"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+</interface>
+<class name="PortIdFactoryImpl"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.graphviz.PortIdFactory">
+</implements>
+<constructor name="PortIdFactoryImpl"
+ type="com.google.inject.grapher.graphviz.PortIdFactoryImpl"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getPortId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.jndi"
+>
+<class name="JndiIntegration"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="fromJndi"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.matcher"
+>
+<class name="AbstractMatcher"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.matcher.Matcher">
+</implements>
+<constructor name="AbstractMatcher"
+ type="com.google.inject.matcher.AbstractMatcher"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="and"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="or"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+</class>
+<interface name="Matcher"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="and"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="matches"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="T">
+</parameter>
+</method>
+<method name="or"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+</interface>
+<class name="Matchers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="any"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="identicalTo"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="inPackage"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackage" type="java.lang.Package">
+</parameter>
+</method>
+<method name="inSubpackage"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackageName" type="java.lang.String">
+</parameter>
+</method>
+<method name="not"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="only"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="returns"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.Method&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="returnType" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+</method>
+<method name="subclassesOf"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="superclass" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.multibindings"
+>
+<class name="MapBinder"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addBinding"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="K">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="permitDuplicates"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="MapBinderBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="containsElement"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="element" type="com.google.inject.spi.Element">
+</parameter>
+</method>
+<method name="getEntries"
+ return="java.util.List&lt;java.util.Map.Entry&lt;?, com.google.inject.Binding&lt;?&gt;&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKeyTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMapKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValueTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="permitsDuplicates"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Multibinder"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addBinding"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="permitDuplicates"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="MultibinderBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="containsElement"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="element" type="com.google.inject.spi.Element">
+</parameter>
+</method>
+<method name="getElementTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSetKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="permitsDuplicates"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="MultibindingsTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mapbinding" type="com.google.inject.multibindings.MapBinderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="multibinding" type="com.google.inject.multibindings.MultibinderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+</package>
+<package name="com.google.inject.name"
+>
+<class name="Named"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Names"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="properties" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="bindProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="properties" type="java.util.Properties">
+</parameter>
+</method>
+<method name="named"
+ return="com.google.inject.name.Named"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.persist"
+>
+<class name="PersistFilter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PersistFilter"
+ type="com.google.inject.persist.PersistFilter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="unitOfWork" type="com.google.inject.persist.UnitOfWork">
+</parameter>
+<parameter name="persistService" type="com.google.inject.persist.PersistService">
+</parameter>
+</constructor>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="doFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletRequest" type="ServletRequest">
+</parameter>
+<parameter name="servletResponse" type="ServletResponse">
+</parameter>
+<parameter name="filterChain" type="FilterChain">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterConfig" type="FilterConfig">
+</parameter>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+</class>
+<class name="PersistModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PersistModule"
+ type="com.google.inject.persist.PersistModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configurePersistence"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getTransactionInterceptor"
+ return="org.aopalliance.intercept.MethodInterceptor"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<interface name="PersistService"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="start"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="stop"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Transactional"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="UnitOfWork"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="begin"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="end"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+</package>
+<package name="com.google.inject.persist.finder"
+>
+<class name="DynamicFinder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DynamicFinder"
+ type="com.google.inject.persist.finder.DynamicFinder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</constructor>
+<method name="from"
+ return="com.google.inject.persist.finder.DynamicFinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</method>
+<method name="metadata"
+ return="com.google.inject.persist.finder.Finder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Finder"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="FirstResult"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="MaxResults"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+</package>
+<package name="com.google.inject.persist.jpa"
+>
+<class name="JpaPersistModule"
+ extends="com.google.inject.persist.PersistModule"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="JpaPersistModule"
+ type="com.google.inject.persist.jpa.JpaPersistModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="jpaUnit" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="addFinder"
+ return="com.google.inject.persist.jpa.JpaPersistModule"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="iface" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="configurePersistence"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getTransactionInterceptor"
+ return="org.aopalliance.intercept.MethodInterceptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="properties"
+ return="com.google.inject.persist.jpa.JpaPersistModule"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="properties" type="java.util.Properties">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.servlet"
+>
+<class name="GuiceFilter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceFilter"
+ type="com.google.inject.servlet.GuiceFilter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="doFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletRequest" type="ServletRequest">
+</parameter>
+<parameter name="servletResponse" type="ServletResponse">
+</parameter>
+<parameter name="filterChain" type="FilterChain">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterConfig" type="FilterConfig">
+</parameter>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+</class>
+<class name="GuiceServletContextListener"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceServletContextListener"
+ type="com.google.inject.servlet.GuiceServletContextListener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="contextDestroyed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletContextEvent" type="ServletContextEvent">
+</parameter>
+</method>
+<method name="contextInitialized"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletContextEvent" type="ServletContextEvent">
+</parameter>
+</method>
+<method name="getInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<interface name="InstanceFilterBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.servlet.ServletModuleBinding">
+</implements>
+<method name="getFilterInstance"
+ return="Filter"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="InstanceServletBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.servlet.ServletModuleBinding">
+</implements>
+<method name="getServletInstance"
+ return="HttpServlet"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="LinkedFilterBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.servlet.ServletModuleBinding">
+</implements>
+<method name="getLinkedKey"
+ return="com.google.inject.Key&lt;? extends Filter&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="LinkedServletBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.servlet.ServletModuleBinding">
+</implements>
+<method name="getLinkedKey"
+ return="com.google.inject.Key&lt;? extends HttpServlet&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="RequestParameters"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="RequestScoped"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ServletModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ServletModule"
+ type="com.google.inject.servlet.ServletModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configureServlets"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="filter"
+ return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="urlPattern" type="java.lang.String">
+</parameter>
+<parameter name="morePatterns" type="java.lang.String...">
+</parameter>
+</method>
+<method name="filterRegex"
+ return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="regex" type="java.lang.String">
+</parameter>
+<parameter name="regexes" type="java.lang.String...">
+</parameter>
+</method>
+<method name="getServletContext"
+ return="ServletContext"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="serve"
+ return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="urlPattern" type="java.lang.String">
+</parameter>
+<parameter name="morePatterns" type="java.lang.String...">
+</parameter>
+</method>
+<method name="serveRegex"
+ return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="regex" type="java.lang.String">
+</parameter>
+<parameter name="regexes" type="java.lang.String...">
+</parameter>
+</method>
+</class>
+<interface name="ServletModule.FilterKeyBindingBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filter" type="Filter">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filter" type="Filter">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ServletModule.ServletKeyBindingBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servlet" type="HttpServlet">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servlet" type="HttpServlet">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ServletModuleBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getInitParams"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPattern"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUriPatternType"
+ return="com.google.inject.servlet.UriPatternType"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="matchesUri"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="java.lang.String">
+</parameter>
+</method>
+</interface>
+<interface name="ServletModuleTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.servlet.InstanceFilterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.servlet.InstanceServletBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.servlet.LinkedFilterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.servlet.LinkedServletBinding">
+</parameter>
+</method>
+</interface>
+<class name="ServletScopes"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="continueRequest"
+ return="java.util.concurrent.Callable&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callable" type="java.util.concurrent.Callable&lt;T&gt;">
+</parameter>
+<parameter name="seedMap" type="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, java.lang.Object&gt;">
+</parameter>
+</method>
+<method name="scopeRequest"
+ return="java.util.concurrent.Callable&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callable" type="java.util.concurrent.Callable&lt;T&gt;">
+</parameter>
+<parameter name="seedMap" type="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, java.lang.Object&gt;">
+</parameter>
+</method>
+<field name="REQUEST"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SESSION"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SessionScoped"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="UriPatternType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.servlet.UriPatternType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.servlet.UriPatternType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
+<package name="com.google.inject.spi"
+>
+<interface name="BindingScopingVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visitEagerSingleton"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitNoScoping"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitScope"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="visitScopeAnnotation"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="BindingTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ConstructorBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getConstructor"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInjectableMembers"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMethodInterceptors"
+ return="java.util.Map&lt;java.lang.reflect.Method, java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ConvertedConstantBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSourceKey"
+ return="com.google.inject.Key&lt;java.lang.String&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeConverterBinding"
+ return="com.google.inject.spi.TypeConverterBinding"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValue"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="DefaultBindingScopingVisitor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingScopingVisitor">
+</implements>
+<constructor name="DefaultBindingScopingVisitor"
+ type="com.google.inject.spi.DefaultBindingScopingVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visitEagerSingleton"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitNoScoping"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="visitScope"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="visitScopeAnnotation"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</class>
+<class name="DefaultBindingTargetVisitor"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<constructor name="DefaultBindingTargetVisitor"
+ type="com.google.inject.spi.DefaultBindingTargetVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructorBinding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="convertedConstantBinding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="exposedBinding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instanceBinding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="linkedKeyBinding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerBinding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerInstanceBinding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerKeyBinding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="untargettedBinding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;? extends T&gt;">
+</parameter>
+</method>
+</class>
+<class name="DefaultElementVisitor"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.ElementVisitor">
+</implements>
+<constructor name="DefaultElementVisitor"
+ type="com.google.inject.spi.DefaultElementVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.DisableCircularProxiesOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectionRequest" type="com.google.inject.spi.InjectionRequest&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interceptorBinding" type="com.google.inject.spi.InterceptorBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="privateElements" type="com.google.inject.spi.PrivateElements">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerLookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.RequireExplicitBindingsOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeBinding" type="com.google.inject.spi.ScopeBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="staticInjectionRequest" type="com.google.inject.spi.StaticInjectionRequest">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeConverterBinding" type="com.google.inject.spi.TypeConverterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeListenerBinding">
+</parameter>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="element" type="com.google.inject.spi.Element">
+</parameter>
+</method>
+</class>
+<class name="Dependency"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="forInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectionPoints" type="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.spi.Dependency&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInjectionPoint"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getParameterIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isNullable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="DisableCircularProxiesOption"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="Element"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="acceptVisitor"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ElementVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.DisableCircularProxiesOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="request" type="com.google.inject.spi.InjectionRequest&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InterceptorBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elements" type="com.google.inject.spi.PrivateElements">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.RequireExplicitBindingsOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ScopeBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="request" type="com.google.inject.spi.StaticInjectionRequest">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeConverterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeListenerBinding">
+</parameter>
+</method>
+</interface>
+<class name="Elements"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Elements"
+ type="com.google.inject.spi.Elements"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="getModule"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elements" type="java.lang.Iterable&lt;? extends com.google.inject.spi.Element&gt;">
+</parameter>
+</method>
+</class>
+<interface name="ExposedBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="applyTo"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getPrivateElements"
+ return="com.google.inject.spi.PrivateElements"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="HasDependencies"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="InjectionListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="afterInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectee" type="I">
+</parameter>
+</method>
+</interface>
+<class name="InjectionPoint"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="forConstructor"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructor" type="java.lang.reflect.Constructor&lt;T&gt;">
+</parameter>
+</method>
+<method name="forConstructor"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructor" type="java.lang.reflect.Constructor&lt;T&gt;">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="forConstructorOf"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="forConstructorOf"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="forInstanceMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="forInstanceMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="forStaticMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="forStaticMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getDeclaringType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDependencies"
+ return="java.util.List&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMember"
+ return="java.lang.reflect.Member"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isOptional"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isToolable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="InjectionRequest"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="InjectionRequest"
+ type="com.google.inject.spi.InjectionRequest"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="instance" type="T">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="R"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;R&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="ConfigurationException" type="com.google.inject.ConfigurationException">
+</exception>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="InstanceBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="InterceptorBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getClassMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInterceptors"
+ return="java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMethodMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="LinkedKeyBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getLinkedKey"
+ return="com.google.inject.Key&lt;? extends T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="MembersInjectorLookup"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="MembersInjectorLookup"
+ type="com.google.inject.spi.MembersInjectorLookup"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getDelegate"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initializeDelegate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delegate" type="com.google.inject.MembersInjector&lt;T&gt;">
+</parameter>
+</method>
+</class>
+<class name="Message"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sources" type="java.util.List&lt;java.lang.Object&gt;">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getCause"
+ return="java.lang.Throwable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessage"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSources"
+ return="java.util.List&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="PrivateElements"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExposedKeys"
+ return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExposedSource"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getProvidedKey"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderInstanceBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProviderInstance"
+ return="com.google.inject.Provider&lt;? extends T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderKeyBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getProviderKey"
+ return="com.google.inject.Key&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="ProviderLookup"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="ProviderLookup"
+ type="com.google.inject.spi.ProviderLookup"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getDelegate"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initializeDelegate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delegate" type="com.google.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+</class>
+<interface name="ProviderWithDependencies"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<implements name="com.google.inject.Provider">
+</implements>
+</interface>
+<interface name="ProviderWithExtensionVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Provider">
+</implements>
+<method name="acceptExtensionVisitor"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;B, V&gt;">
+</parameter>
+<parameter name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends B&gt;">
+</parameter>
+</method>
+</interface>
+<class name="RequireExplicitBindingsOption"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ScopeBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getAnnotationType"
+ return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getScope"
+ return="com.google.inject.Scope"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="StaticInjectionRequest"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="ConfigurationException" type="com.google.inject.ConfigurationException">
+</exception>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="java.lang.Class&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Toolable"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="TypeConverter"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="convert"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+<parameter name="toType" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+</interface>
+<class name="TypeConverterBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="TypeConverterBinding"
+ type="com.google.inject.spi.TypeConverterBinding"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="typeConverter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeConverter"
+ return="com.google.inject.spi.TypeConverter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="TypeEncounter"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="register"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="membersInjector" type="com.google.inject.MembersInjector&lt;? super I&gt;">
+</parameter>
+</method>
+<method name="register"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="com.google.inject.spi.InjectionListener&lt;? super I&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="TypeListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="hear"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;I&gt;">
+</parameter>
+<parameter name="encounter" type="com.google.inject.spi.TypeEncounter&lt;I&gt;">
+</parameter>
+</method>
+</interface>
+<class name="TypeListenerBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getListener"
+ return="com.google.inject.spi.TypeListener"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="UntargettedBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+</interface>
+</package>
+<package name="com.google.inject.spring"
+>
+<class name="SpringIntegration"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindAll"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="beanFactory" type="ListableBeanFactory">
+</parameter>
+</method>
+<method name="fromSpring"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.throwingproviders"
+>
+<interface name="CheckedProvider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+</interface>
+<class name="CheckedProvides"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="ThrowingProvider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.throwingproviders.CheckedProvider">
+</implements>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+</interface>
+<class name="ThrowingProviderBinder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bind"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceType" type="java.lang.Class&lt;P&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="create"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="forModule"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+</class>
+<class name="ThrowingProviderBinder.SecondaryBinder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ThrowingProviderBinder.SecondaryBinder"
+ type="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceType" type="java.lang.Class&lt;P&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.reflect.Type">
+</parameter>
+</constructor>
+<method name="annotatedWith"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="P">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetKey" type="com.google.inject.Key&lt;? extends P&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetType" type="java.lang.Class&lt;? extends P&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.tools.jmx"
+>
+<interface name="ManagedBindingMBean"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getKey"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Manager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Manager"
+ type="com.google.inject.tools.jmx.Manager"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="main"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+<method name="manage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="domain" type="java.lang.String">
+</parameter>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+<method name="manage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="server" type="javax.management.MBeanServer">
+</parameter>
+<parameter name="domain" type="java.lang.String">
+</parameter>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.util"
+>
+<class name="Modules"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="combine"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="combine"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="override"
+ return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="override"
+ return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<field name="EMPTY_MODULE"
+ type="com.google.inject.Module"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="Modules.OverriddenModuleBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="with"
+ return="com.google.inject.Module"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overrides" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="with"
+ return="com.google.inject.Module"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overrides" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+</interface>
+<class name="Providers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="guicify"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="javax.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+<method name="of"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+</class>
+<class name="Types"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="arrayOf"
+ return="java.lang.reflect.GenericArrayType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="componentType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="listOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elementType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="mapOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="valueType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="newParameterizedType"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rawType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="typeArguments" type="java.lang.reflect.Type...">
+</parameter>
+</method>
+<method name="newParameterizedTypeWithOwner"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ownerType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="rawType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="typeArguments" type="java.lang.reflect.Type...">
+</parameter>
+</method>
+<method name="providerOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providedType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="setOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elementType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="subtypeOf"
+ return="java.lang.reflect.WildcardType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bound" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="supertypeOf"
+ return="java.lang.reflect.WildcardType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bound" type="java.lang.reflect.Type">
+</parameter>
+</method>
+</class>
+</package>
+</api>
diff --git a/lib/build/guice-4.0.xml b/lib/build/guice-4.0.xml
new file mode 100644
index 0000000..2d6e59e
--- /dev/null
+++ b/lib/build/guice-4.0.xml
@@ -0,0 +1,11409 @@
+<api>
+<package name="com.google.inject"
+>
+<class name="AbstractModule"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Module">
+</implements>
+<constructor name="AbstractModule"
+ type="com.google.inject.AbstractModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="clazz" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="bindingMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.Binding&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.ProvisionListener...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="binder"
+ return="com.google.inject.Binder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="builder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<interface name="Binder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bindingMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.Binding&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listeners" type="com.google.inject.spi.ProvisionListener...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="disableCircularProxies"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="newPrivateBinder"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="requireAtInjectOnConstructors"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="requireExactBindingAnnotations"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="requireExplicitBindings"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="skipSources"
+ return="com.google.inject.Binder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classesToSkip" type="java.lang.Class...">
+</parameter>
+</method>
+<method name="withSource"
+ return="com.google.inject.Binder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<interface name="Binding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptScopingVisitor"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.BindingScopingVisitor&lt;V&gt;">
+</parameter>
+</method>
+<method name="acceptTargetVisitor"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;? super T, V&gt;">
+</parameter>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="BindingAnnotation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ConfigurationException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ConfigurationException"
+ type="com.google.inject.ConfigurationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPartialValue"
+ return="E"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="withPartialValue"
+ return="com.google.inject.ConfigurationException"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="partialValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="CreationException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CreationException"
+ type="com.google.inject.CreationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.util.Collection&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Exposed"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Guice"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="createInjector"
+ return="com.google.inject.Injector"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+</class>
+<class name="ImplementedBy"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Inject"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="Injector"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createChildInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="createChildInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="findBindingsByType"
+ return="java.util.List&lt;com.google.inject.Binding&lt;T&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getAllBindings"
+ return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getBindings"
+ return="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExistingBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getParent"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getScopeBindings"
+ return="java.util.Map&lt;java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;, com.google.inject.Scope&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeConverterBindings"
+ return="java.util.Set&lt;com.google.inject.spi.TypeConverterBinding&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="injectMembers"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="Key"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</constructor>
+<constructor name="Key"
+ type="com.google.inject.Key"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</constructor>
+<method name="equals"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="getAnnotation"
+ return="java.lang.annotation.Annotation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAnnotationType"
+ return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasAttributes"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hashCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="ofType"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="ofType"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="ofType"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="withoutAttributes"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="MembersInjector"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="injectMembers"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+</interface>
+<interface name="Module"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+</interface>
+<class name="OutOfScopeException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<constructor name="OutOfScopeException"
+ type="com.google.inject.OutOfScopeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+</class>
+<interface name="PrivateBinder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binder">
+</implements>
+<method name="expose"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="skipSources"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="classesToSkip" type="java.lang.Class...">
+</parameter>
+</method>
+<method name="withSource"
+ return="com.google.inject.PrivateBinder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="PrivateModule"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Module">
+</implements>
+<constructor name="PrivateModule"
+ type="com.google.inject.PrivateModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.binder.AnnotatedBindingBuilder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="clazz" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bindConstant"
+ return="com.google.inject.binder.AnnotatedConstantBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="classMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="bindingMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.Binding&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listeners" type="com.google.inject.spi.ProvisionListener...">
+</parameter>
+</method>
+<method name="bindListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="listener" type="com.google.inject.spi.TypeListener">
+</parameter>
+</method>
+<method name="bindScope"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="binder"
+ return="com.google.inject.PrivateBinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="convertToTypes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="converter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</method>
+<method name="currentStage"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="expose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="expose"
+ return="com.google.inject.binder.AnnotatedElementBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="install"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+<method name="requestInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestStaticInjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="types" type="java.lang.Class&lt;?&gt;...">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="requireBinding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<class name="ProvidedBy"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="Provider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="javax.inject.Provider">
+</implements>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Provides"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ProvisionException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messages" type="java.lang.Iterable&lt;com.google.inject.spi.Message&gt;">
+</parameter>
+</constructor>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="ProvisionException"
+ type="com.google.inject.ProvisionException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<method name="getErrorMessages"
+ return="java.util.Collection&lt;com.google.inject.spi.Message&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="Scope"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="scope"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+<parameter name="unscoped" type="com.google.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="ScopeAnnotation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Scopes"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="isCircularProxy"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="object" type="java.lang.Object">
+</parameter>
+</method>
+<method name="isScoped"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="isSingleton"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+</method>
+<field name="NO_SCOPE"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SINGLETON"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Singleton"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Stage"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.Stage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.Stage[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="TypeLiteral"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="TypeLiteral"
+ type="com.google.inject.TypeLiteral"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<method name="equals"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="getExceptionTypes"
+ return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodOrConstructor" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getFieldType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="field" type="java.lang.reflect.Field">
+</parameter>
+</method>
+<method name="getParameterTypes"
+ return="java.util.List&lt;com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodOrConstructor" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getRawType"
+ return="java.lang.Class&lt;? super T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getReturnType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</method>
+<method name="getSupertype"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="supertype" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getType"
+ return="java.lang.reflect.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hashCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
+<package name="com.google.inject.assistedinject"
+>
+<class name="Assisted"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="AssistedInject"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="AssistedInjectBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getAssistedMethods"
+ return="java.util.Collection&lt;com.google.inject.assistedinject.AssistedMethod&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="AssistedInjectTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="assistedInjectBinding" type="com.google.inject.assistedinject.AssistedInjectBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="AssistedMethod"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFactoryMethod"
+ return="java.lang.reflect.Method"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getImplementationConstructor"
+ return="java.lang.reflect.Constructor&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getImplementationType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="FactoryModuleBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FactoryModuleBuilder"
+ type="com.google.inject.assistedinject.FactoryModuleBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="build"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryInterface" type="com.google.inject.Key&lt;F&gt;">
+</parameter>
+</method>
+<method name="build"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryInterface" type="com.google.inject.TypeLiteral&lt;F&gt;">
+</parameter>
+</method>
+<method name="build"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryInterface" type="java.lang.Class&lt;F&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+<parameter name="target" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="implement"
+ return="com.google.inject.assistedinject.FactoryModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+<parameter name="target" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+</class>
+<class name="FactoryProvider"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<implements name="com.google.inject.Provider">
+</implements>
+<method name="get"
+ return="F"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newFactory"
+ return="com.google.inject.Provider&lt;F&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryType" type="com.google.inject.TypeLiteral&lt;F&gt;">
+</parameter>
+<parameter name="implementationType" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="newFactory"
+ return="com.google.inject.Provider&lt;F&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factoryType" type="java.lang.Class&lt;F&gt;">
+</parameter>
+<parameter name="implementationType" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.binder"
+>
+<interface name="AnnotatedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.binder.LinkedBindingBuilder">
+</implements>
+<method name="annotatedWith"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="AnnotatedConstantBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="com.google.inject.binder.ConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.binder.ConstantBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="AnnotatedElementBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+</interface>
+<interface name="ConstantBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="E">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="byte">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="char">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="double">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="float">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="long">
+</parameter>
+</method>
+<method name="to"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="short">
+</parameter>
+</method>
+</interface>
+<interface name="LinkedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.binder.ScopedBindingBuilder">
+</implements>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetKey" type="com.google.inject.Key&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="implementation" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="toConstructor"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructor" type="java.lang.reflect.Constructor&lt;S&gt;">
+</parameter>
+</method>
+<method name="toConstructor"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructor" type="java.lang.reflect.Constructor&lt;S&gt;">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;? extends S&gt;">
+</parameter>
+</method>
+<method name="toInstance"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerKey" type="com.google.inject.Key&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="com.google.inject.Provider&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerType" type="com.google.inject.TypeLiteral&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerType" type="java.lang.Class&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;">
+</parameter>
+</method>
+<method name="toProvider"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="javax.inject.Provider&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ScopedBindingBuilder"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="asEagerSingleton"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="in"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="in"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</interface>
+</package>
+<package name="com.google.inject.grapher"
+>
+<class name="AbstractInjectorGrapher"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.InjectorGrapher">
+</implements>
+<constructor name="AbstractInjectorGrapher"
+ type="com.google.inject.grapher.AbstractInjectorGrapher"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="AbstractInjectorGrapher"
+ type="com.google.inject.grapher.AbstractInjectorGrapher"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="options" type="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters">
+</parameter>
+</constructor>
+<method name="graph"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="graph"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+<parameter name="root" type="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newBindingEdge"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.BindingEdge">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newDependencyEdge"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.DependencyEdge">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newImplementationNode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.ImplementationNode">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newInstanceNode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.InstanceNode">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newInterfaceNode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.InterfaceNode">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="postProcess"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="reset"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="AbstractInjectorGrapher.GrapherParameters"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GrapherParameters"
+ type="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getAliasCreator"
+ return="com.google.inject.grapher.AliasCreator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEdgeCreator"
+ return="com.google.inject.grapher.EdgeCreator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNodeCreator"
+ return="com.google.inject.grapher.NodeCreator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRootKeySetCreator"
+ return="com.google.inject.grapher.RootKeySetCreator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAliasCreator"
+ return="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="aliasCreator" type="com.google.inject.grapher.AliasCreator">
+</parameter>
+</method>
+<method name="setEdgeCreator"
+ return="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="edgeCreator" type="com.google.inject.grapher.EdgeCreator">
+</parameter>
+</method>
+<method name="setNodeCreator"
+ return="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nodeCreator" type="com.google.inject.grapher.NodeCreator">
+</parameter>
+</method>
+<method name="setRootKeySetCreator"
+ return="com.google.inject.grapher.AbstractInjectorGrapher.GrapherParameters"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rootKeySetCreator" type="com.google.inject.grapher.RootKeySetCreator">
+</parameter>
+</method>
+</class>
+<class name="Alias"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Alias"
+ type="com.google.inject.grapher.Alias"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="toId" type="com.google.inject.grapher.NodeId">
+</parameter>
+</constructor>
+<method name="getFromId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getToId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="AliasCreator"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createAliases"
+ return="java.lang.Iterable&lt;com.google.inject.grapher.Alias&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bindings" type="java.lang.Iterable&lt;com.google.inject.Binding&lt;?&gt;&gt;">
+</parameter>
+</method>
+</interface>
+<class name="BindingEdge"
+ extends="com.google.inject.grapher.Edge"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="BindingEdge"
+ type="com.google.inject.grapher.BindingEdge"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="toId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="type" type="com.google.inject.grapher.BindingEdge.Type">
+</parameter>
+</constructor>
+<method name="copy"
+ return="com.google.inject.grapher.Edge"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="toId" type="com.google.inject.grapher.NodeId">
+</parameter>
+</method>
+<method name="getType"
+ return="com.google.inject.grapher.BindingEdge.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="BindingEdge.Type"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.BindingEdge.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.BindingEdge.Type[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="DefaultRootKeySetCreator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.RootKeySetCreator">
+</implements>
+<constructor name="DefaultRootKeySetCreator"
+ type="com.google.inject.grapher.DefaultRootKeySetCreator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getRootKeys"
+ return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+</class>
+<class name="DependencyEdge"
+ extends="com.google.inject.grapher.Edge"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DependencyEdge"
+ type="com.google.inject.grapher.DependencyEdge"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="toId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="injectionPoint" type="com.google.inject.spi.InjectionPoint">
+</parameter>
+</constructor>
+<method name="copy"
+ return="com.google.inject.grapher.Edge"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="toId" type="com.google.inject.grapher.NodeId">
+</parameter>
+</method>
+<method name="getInjectionPoint"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Edge"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Edge"
+ type="com.google.inject.grapher.Edge"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="fromId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="toId" type="com.google.inject.grapher.NodeId">
+</parameter>
+</constructor>
+<method name="copy"
+ return="com.google.inject.grapher.Edge"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="toId" type="com.google.inject.grapher.NodeId">
+</parameter>
+</method>
+<method name="getFromId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getToId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="EdgeCreator"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getEdges"
+ return="java.lang.Iterable&lt;com.google.inject.grapher.Edge&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bindings" type="java.lang.Iterable&lt;com.google.inject.Binding&lt;?&gt;&gt;">
+</parameter>
+</method>
+</interface>
+<class name="ImplementationNode"
+ extends="com.google.inject.grapher.Node"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ImplementationNode"
+ type="com.google.inject.grapher.ImplementationNode"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="members" type="java.util.Collection&lt;java.lang.reflect.Member&gt;">
+</parameter>
+</constructor>
+<method name="copy"
+ return="com.google.inject.grapher.Node"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="com.google.inject.grapher.NodeId">
+</parameter>
+</method>
+<method name="getMembers"
+ return="java.util.Collection&lt;java.lang.reflect.Member&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="InjectorGrapher"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="graph"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="graph"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+<parameter name="root" type="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</interface>
+<class name="InstanceNode"
+ extends="com.google.inject.grapher.Node"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="InstanceNode"
+ type="com.google.inject.grapher.InstanceNode"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+<parameter name="members" type="java.lang.Iterable&lt;java.lang.reflect.Member&gt;">
+</parameter>
+</constructor>
+<method name="copy"
+ return="com.google.inject.grapher.Node"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="com.google.inject.grapher.NodeId">
+</parameter>
+</method>
+<method name="getInstance"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMembers"
+ return="java.lang.Iterable&lt;java.lang.reflect.Member&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="InterfaceNode"
+ extends="com.google.inject.grapher.Node"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="InterfaceNode"
+ type="com.google.inject.grapher.InterfaceNode"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</constructor>
+<method name="copy"
+ return="com.google.inject.grapher.Node"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="com.google.inject.grapher.NodeId">
+</parameter>
+</method>
+</class>
+<interface name="NameFactory"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getAnnotationName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getClassName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getInstanceName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="getMemberName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getSourceName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="Node"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Node"
+ type="com.google.inject.grapher.Node"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="id" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</constructor>
+<method name="copy"
+ return="com.google.inject.grapher.Node"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="com.google.inject.grapher.NodeId">
+</parameter>
+</method>
+<method name="getId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="NodeCreator"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getNodes"
+ return="java.lang.Iterable&lt;com.google.inject.grapher.Node&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bindings" type="java.lang.Iterable&lt;com.google.inject.Binding&lt;?&gt;&gt;">
+</parameter>
+</method>
+</interface>
+<class name="NodeId"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getKey"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newInstanceId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="newTypeId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+</class>
+<class name="NodeId.NodeType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.NodeId.NodeType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.NodeId.NodeType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="RootKeySetCreator"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getRootKeys"
+ return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+</interface>
+<class name="ShortNameFactory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.NameFactory">
+</implements>
+<constructor name="ShortNameFactory"
+ type="com.google.inject.grapher.ShortNameFactory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getAnnotationName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getClassName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getFileString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="stackTraceElement" type="java.lang.StackTraceElement">
+</parameter>
+</method>
+<method name="getInstanceName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="java.lang.Object">
+</parameter>
+</method>
+<method name="getMemberName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+<method name="getMethodString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</method>
+<method name="getSourceName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="TransitiveDependencyVisitor"
+ extends="com.google.inject.spi.DefaultBindingTargetVisitor"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="TransitiveDependencyVisitor"
+ type="com.google.inject.grapher.TransitiveDependencyVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConstructorBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InstanceBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;?&gt;">
+</parameter>
+</method>
+<method name="visitOther"
+ return="java.util.Collection&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.grapher.graphviz"
+>
+<class name="ArrowType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.ArrowType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.ArrowType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="CompassPoint"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.CompassPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.CompassPoint[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="EdgeStyle"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.EdgeStyle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.EdgeStyle[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="GraphvizEdge"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GraphvizEdge"
+ type="com.google.inject.grapher.graphviz.GraphvizEdge"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tailNodeId" type="com.google.inject.grapher.NodeId">
+</parameter>
+<parameter name="headNodeId" type="com.google.inject.grapher.NodeId">
+</parameter>
+</constructor>
+<method name="getArrowHead"
+ return="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getArrowTail"
+ return="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeadCompassPoint"
+ return="com.google.inject.grapher.graphviz.CompassPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeadNodeId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeadPortId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStyle"
+ return="com.google.inject.grapher.graphviz.EdgeStyle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTailCompassPoint"
+ return="com.google.inject.grapher.graphviz.CompassPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTailNodeId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTailPortId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setArrowHead"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="arrowHead" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;">
+</parameter>
+</method>
+<method name="setArrowTail"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="arrowTail" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;">
+</parameter>
+</method>
+<method name="setHeadCompassPoint"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="headCompassPoint" type="com.google.inject.grapher.graphviz.CompassPoint">
+</parameter>
+</method>
+<method name="setHeadPortId"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="headPortId" type="java.lang.String">
+</parameter>
+</method>
+<method name="setStyle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="style" type="com.google.inject.grapher.graphviz.EdgeStyle">
+</parameter>
+</method>
+<method name="setTailCompassPoint"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tailCompassPoint" type="com.google.inject.grapher.graphviz.CompassPoint">
+</parameter>
+</method>
+<method name="setTailPortId"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tailPortId" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="GraphvizGrapher"
+ extends="com.google.inject.grapher.AbstractInjectorGrapher"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="finish"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getArrowString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="arrows" type="java.util.List&lt;com.google.inject.grapher.graphviz.ArrowType&gt;">
+</parameter>
+</method>
+<method name="getEdgeAttributes"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</method>
+<method name="getEdgeEndPoint"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="nodeId" type="java.lang.String">
+</parameter>
+<parameter name="portId" type="java.lang.String">
+</parameter>
+<parameter name="compassPoint" type="com.google.inject.grapher.graphviz.CompassPoint">
+</parameter>
+</method>
+<method name="getGraphAttributes"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getNodeAttributes"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</method>
+<method name="getNodeLabel"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</method>
+<method name="htmlEscape"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="str" type="java.lang.String">
+</parameter>
+</method>
+<method name="htmlEscape"
+ return="java.util.List&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="elements" type="java.util.List&lt;java.lang.String&gt;">
+</parameter>
+</method>
+<method name="newBindingEdge"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.BindingEdge">
+</parameter>
+</method>
+<method name="newDependencyEdge"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.DependencyEdge">
+</parameter>
+</method>
+<method name="newImplementationNode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.ImplementationNode">
+</parameter>
+</method>
+<method name="newInstanceNode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.InstanceNode">
+</parameter>
+</method>
+<method name="newInterfaceNode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.InterfaceNode">
+</parameter>
+</method>
+<method name="postProcess"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="renderEdge"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="edge" type="com.google.inject.grapher.graphviz.GraphvizEdge">
+</parameter>
+</method>
+<method name="renderNode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="node" type="com.google.inject.grapher.graphviz.GraphvizNode">
+</parameter>
+</method>
+<method name="reset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="setOut"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="java.io.PrintWriter">
+</parameter>
+</method>
+<method name="setRankdir"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rankdir" type="java.lang.String">
+</parameter>
+</method>
+<method name="start"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<class name="GraphvizModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GraphvizModule"
+ type="com.google.inject.grapher.graphviz.GraphvizModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<class name="GraphvizNode"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GraphvizNode"
+ type="com.google.inject.grapher.graphviz.GraphvizNode"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nodeId" type="com.google.inject.grapher.NodeId">
+</parameter>
+</constructor>
+<method name="addField"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="portId" type="java.lang.String">
+</parameter>
+<parameter name="title" type="java.lang.String">
+</parameter>
+</method>
+<method name="addSubtitle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+<parameter name="subtitle" type="java.lang.String">
+</parameter>
+</method>
+<method name="getFields"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeaderBackgroundColor"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeaderTextColor"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIdentifier"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNodeId"
+ return="com.google.inject.grapher.NodeId"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getShape"
+ return="com.google.inject.grapher.graphviz.NodeShape"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStyle"
+ return="com.google.inject.grapher.graphviz.NodeStyle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubtitles"
+ return="java.util.List&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTitle"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setHeaderBackgroundColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="headerBackgroundColor" type="java.lang.String">
+</parameter>
+</method>
+<method name="setHeaderTextColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="headerTextColor" type="java.lang.String">
+</parameter>
+</method>
+<method name="setIdentifier"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="identifier" type="java.lang.String">
+</parameter>
+</method>
+<method name="setShape"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shape" type="com.google.inject.grapher.graphviz.NodeShape">
+</parameter>
+</method>
+<method name="setStyle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="style" type="com.google.inject.grapher.graphviz.NodeStyle">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="NodeShape"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.NodeShape"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.NodeShape[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="NodeStyle"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.grapher.graphviz.NodeStyle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.grapher.graphviz.NodeStyle[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="PortIdFactory"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getPortId"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+</interface>
+<class name="PortIdFactoryImpl"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.grapher.graphviz.PortIdFactory">
+</implements>
+<constructor name="PortIdFactoryImpl"
+ type="com.google.inject.grapher.graphviz.PortIdFactoryImpl"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getPortId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="member" type="java.lang.reflect.Member">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.jndi"
+>
+<class name="JndiIntegration"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="fromJndi"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.matcher"
+>
+<class name="AbstractMatcher"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.matcher.Matcher">
+</implements>
+<constructor name="AbstractMatcher"
+ type="com.google.inject.matcher.AbstractMatcher"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="and"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="or"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+</class>
+<interface name="Matcher"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="and"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="matches"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="T">
+</parameter>
+</method>
+<method name="or"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+</interface>
+<class name="Matchers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="annotatedWith"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.AnnotatedElement&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="any"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="identicalTo"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="inPackage"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackage" type="java.lang.Package">
+</parameter>
+</method>
+<method name="inSubpackage"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackageName" type="java.lang.String">
+</parameter>
+</method>
+<method name="not"
+ return="com.google.inject.matcher.Matcher&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="com.google.inject.matcher.Matcher&lt;? super T&gt;">
+</parameter>
+</method>
+<method name="only"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="returns"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.reflect.Method&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="returnType" type="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;">
+</parameter>
+</method>
+<method name="subclassesOf"
+ return="com.google.inject.matcher.Matcher&lt;java.lang.Class&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="superclass" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.multibindings"
+>
+<class name="MapBinder"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addBinding"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="K">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="com.google.inject.TypeLiteral&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="com.google.inject.TypeLiteral&lt;V&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newMapBinder"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="keyType" type="java.lang.Class&lt;K&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.Class&lt;V&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="permitDuplicates"
+ return="com.google.inject.multibindings.MapBinder&lt;K, V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="MapBinderBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="containsElement"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="element" type="com.google.inject.spi.Element">
+</parameter>
+</method>
+<method name="getEntries"
+ return="java.util.List&lt;java.util.Map.Entry&lt;?, com.google.inject.Binding&lt;?&gt;&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKeyTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMapKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValueTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="permitsDuplicates"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Multibinder"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addBinding"
+ return="com.google.inject.binder.LinkedBindingBuilder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="newSetBinder"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="permitDuplicates"
+ return="com.google.inject.multibindings.Multibinder&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="MultibinderBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="containsElement"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="element" type="com.google.inject.spi.Element">
+</parameter>
+</method>
+<method name="getElementTypeLiteral"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSetKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="permitsDuplicates"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="MultibindingsTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mapbinding" type="com.google.inject.multibindings.MapBinderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="multibinding" type="com.google.inject.multibindings.MultibinderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+</package>
+<package name="com.google.inject.name"
+>
+<class name="Named"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="Names"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="properties" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="bindProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="properties" type="java.util.Properties">
+</parameter>
+</method>
+<method name="named"
+ return="com.google.inject.name.Named"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.persist"
+>
+<class name="PersistFilter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PersistFilter"
+ type="com.google.inject.persist.PersistFilter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="unitOfWork" type="com.google.inject.persist.UnitOfWork">
+</parameter>
+<parameter name="persistService" type="com.google.inject.persist.PersistService">
+</parameter>
+</constructor>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="doFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletRequest" type="ServletRequest">
+</parameter>
+<parameter name="servletResponse" type="ServletResponse">
+</parameter>
+<parameter name="filterChain" type="FilterChain">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterConfig" type="FilterConfig">
+</parameter>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+</class>
+<class name="PersistModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PersistModule"
+ type="com.google.inject.persist.PersistModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configurePersistence"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getTransactionInterceptor"
+ return="org.aopalliance.intercept.MethodInterceptor"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<interface name="PersistService"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="start"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="stop"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Transactional"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="UnitOfWork"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="begin"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="end"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+</package>
+<package name="com.google.inject.persist.finder"
+>
+<class name="DynamicFinder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DynamicFinder"
+ type="com.google.inject.persist.finder.DynamicFinder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</constructor>
+<method name="from"
+ return="com.google.inject.persist.finder.DynamicFinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.reflect.Method">
+</parameter>
+</method>
+<method name="metadata"
+ return="com.google.inject.persist.finder.Finder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Finder"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="FirstResult"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="MaxResults"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+</package>
+<package name="com.google.inject.persist.jpa"
+>
+<class name="JpaPersistModule"
+ extends="com.google.inject.persist.PersistModule"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="JpaPersistModule"
+ type="com.google.inject.persist.jpa.JpaPersistModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="jpaUnit" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="addFinder"
+ return="com.google.inject.persist.jpa.JpaPersistModule"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="iface" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="configurePersistence"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getTransactionInterceptor"
+ return="org.aopalliance.intercept.MethodInterceptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="properties"
+ return="com.google.inject.persist.jpa.JpaPersistModule"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="properties" type="java.util.Properties">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.servlet"
+>
+<class name="GuiceFilter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceFilter"
+ type="com.google.inject.servlet.GuiceFilter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="doFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletRequest" type="ServletRequest">
+</parameter>
+<parameter name="servletResponse" type="ServletResponse">
+</parameter>
+<parameter name="filterChain" type="FilterChain">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterConfig" type="FilterConfig">
+</parameter>
+<exception name="ServletException" type="ServletException">
+</exception>
+</method>
+</class>
+<class name="GuiceServletContextListener"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GuiceServletContextListener"
+ type="com.google.inject.servlet.GuiceServletContextListener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="contextDestroyed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletContextEvent" type="ServletContextEvent">
+</parameter>
+</method>
+<method name="contextInitialized"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletContextEvent" type="ServletContextEvent">
+</parameter>
+</method>
+<method name="getInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+</class>
+<interface name="InstanceFilterBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.servlet.ServletModuleBinding">
+</implements>
+<method name="getFilterInstance"
+ return="Filter"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="InstanceServletBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.servlet.ServletModuleBinding">
+</implements>
+<method name="getServletInstance"
+ return="HttpServlet"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="LinkedFilterBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.servlet.ServletModuleBinding">
+</implements>
+<method name="getLinkedKey"
+ return="com.google.inject.Key&lt;? extends Filter&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="LinkedServletBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.servlet.ServletModuleBinding">
+</implements>
+<method name="getLinkedKey"
+ return="com.google.inject.Key&lt;? extends HttpServlet&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="RequestParameters"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="RequestScoped"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ScopingException"
+ extends="java.lang.IllegalStateException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ScopingException"
+ type="com.google.inject.servlet.ScopingException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="ScopingOnly"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ServletModule"
+ extends="com.google.inject.AbstractModule"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ServletModule"
+ type="com.google.inject.servlet.ServletModule"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="configure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="configureServlets"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="filter"
+ return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="urlPattern" type="java.lang.String">
+</parameter>
+<parameter name="morePatterns" type="java.lang.String...">
+</parameter>
+</method>
+<method name="filterRegex"
+ return="com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="regex" type="java.lang.String">
+</parameter>
+<parameter name="regexes" type="java.lang.String...">
+</parameter>
+</method>
+<method name="getServletContext"
+ return="ServletContext"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="serve"
+ return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="urlPattern" type="java.lang.String">
+</parameter>
+<parameter name="morePatterns" type="java.lang.String...">
+</parameter>
+</method>
+<method name="serveRegex"
+ return="com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="regex" type="java.lang.String">
+</parameter>
+<parameter name="regexes" type="java.lang.String...">
+</parameter>
+</method>
+</class>
+<interface name="ServletModule.FilterKeyBindingBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filter" type="Filter">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filter" type="Filter">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="com.google.inject.Key&lt;? extends Filter&gt;">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;">
+</parameter>
+</method>
+<method name="through"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filterKey" type="java.lang.Class&lt;? extends Filter&gt;">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ServletModule.ServletKeyBindingBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servlet" type="HttpServlet">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servlet" type="HttpServlet">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="com.google.inject.Key&lt;? extends HttpServlet&gt;">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="servletKey" type="java.lang.Class&lt;? extends HttpServlet&gt;">
+</parameter>
+<parameter name="initParams" type="java.util.Map&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ServletModuleBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getInitParams"
+ return="java.util.Map&lt;java.lang.String, java.lang.String&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPattern"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUriPatternType"
+ return="com.google.inject.servlet.UriPatternType"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="matchesUri"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="java.lang.String">
+</parameter>
+</method>
+</interface>
+<interface name="ServletModuleTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.servlet.InstanceFilterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.servlet.InstanceServletBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.servlet.LinkedFilterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.servlet.LinkedServletBinding">
+</parameter>
+</method>
+</interface>
+<class name="ServletScopes"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="continueRequest"
+ return="java.util.concurrent.Callable&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callable" type="java.util.concurrent.Callable&lt;T&gt;">
+</parameter>
+<parameter name="seedMap" type="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, java.lang.Object&gt;">
+</parameter>
+</method>
+<method name="isRequestScoped"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;?&gt;">
+</parameter>
+</method>
+<method name="scopeRequest"
+ return="java.util.concurrent.Callable&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callable" type="java.util.concurrent.Callable&lt;T&gt;">
+</parameter>
+<parameter name="seedMap" type="java.util.Map&lt;com.google.inject.Key&lt;?&gt;, java.lang.Object&gt;">
+</parameter>
+</method>
+<method name="transferRequest"
+ return="java.util.concurrent.Callable&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callable" type="java.util.concurrent.Callable&lt;T&gt;">
+</parameter>
+</method>
+<field name="REQUEST"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SESSION"
+ type="com.google.inject.Scope"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SessionScoped"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="UriPatternType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="com.google.inject.servlet.UriPatternType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="com.google.inject.servlet.UriPatternType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
+<package name="com.google.inject.spi"
+>
+<interface name="BindingScopingVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visitEagerSingleton"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitNoScoping"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitScope"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="visitScopeAnnotation"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="BindingTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ConstructorBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getConstructor"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInjectableMembers"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMethodInterceptors"
+ return="java.util.Map&lt;java.lang.reflect.Method, java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ConvertedConstantBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSourceKey"
+ return="com.google.inject.Key&lt;java.lang.String&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeConverterBinding"
+ return="com.google.inject.spi.TypeConverterBinding"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValue"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="DefaultBindingScopingVisitor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingScopingVisitor">
+</implements>
+<constructor name="DefaultBindingScopingVisitor"
+ type="com.google.inject.spi.DefaultBindingScopingVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visitEagerSingleton"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitNoScoping"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="visitScope"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scope" type="com.google.inject.Scope">
+</parameter>
+</method>
+<method name="visitScopeAnnotation"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeAnnotation" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+</class>
+<class name="DefaultBindingTargetVisitor"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<constructor name="DefaultBindingTargetVisitor"
+ type="com.google.inject.spi.DefaultBindingTargetVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructorBinding" type="com.google.inject.spi.ConstructorBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="convertedConstantBinding" type="com.google.inject.spi.ConvertedConstantBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="exposedBinding" type="com.google.inject.spi.ExposedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instanceBinding" type="com.google.inject.spi.InstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="linkedKeyBinding" type="com.google.inject.spi.LinkedKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerBinding" type="com.google.inject.spi.ProviderBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerInstanceBinding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerKeyBinding" type="com.google.inject.spi.ProviderKeyBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="untargettedBinding" type="com.google.inject.spi.UntargettedBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;? extends T&gt;">
+</parameter>
+</method>
+</class>
+<class name="DefaultElementVisitor"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.ElementVisitor">
+</implements>
+<constructor name="DefaultElementVisitor"
+ type="com.google.inject.spi.DefaultElementVisitor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.DisableCircularProxiesOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectionRequest" type="com.google.inject.spi.InjectionRequest&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interceptorBinding" type="com.google.inject.spi.InterceptorBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="privateElements" type="com.google.inject.spi.PrivateElements">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providerLookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProvisionListenerBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.RequireAtInjectOnConstructorsOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.RequireExactBindingAnnotationsOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.RequireExplicitBindingsOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scopeBinding" type="com.google.inject.spi.ScopeBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="staticInjectionRequest" type="com.google.inject.spi.StaticInjectionRequest">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeConverterBinding" type="com.google.inject.spi.TypeConverterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeListenerBinding">
+</parameter>
+</method>
+<method name="visitOther"
+ return="V"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="element" type="com.google.inject.spi.Element">
+</parameter>
+</method>
+</class>
+<class name="Dependency"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="forInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectionPoints" type="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;">
+</parameter>
+</method>
+<method name="get"
+ return="com.google.inject.spi.Dependency&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getInjectionPoint"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getParameterIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isNullable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="DependencyAndSource"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DependencyAndSource"
+ type="com.google.inject.spi.DependencyAndSource"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dependency" type="com.google.inject.spi.Dependency&lt;?&gt;">
+</parameter>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+</constructor>
+<method name="getBindingSource"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDependency"
+ return="com.google.inject.spi.Dependency&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="DisableCircularProxiesOption"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="Element"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="acceptVisitor"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="ElementSource"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getDeclaringSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getModuleClassNames"
+ return="java.util.List&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getModuleConfigurePositionsInStackTrace"
+ return="java.util.List&lt;java.lang.Integer&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOriginalElementSource"
+ return="com.google.inject.spi.ElementSource"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStackTrace"
+ return="java.lang.StackTraceElement[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="ElementVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.Binding&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.DisableCircularProxiesOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="request" type="com.google.inject.spi.InjectionRequest&lt;?&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.InterceptorBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.MembersInjectorLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elements" type="com.google.inject.spi.PrivateElements">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lookup" type="com.google.inject.spi.ProviderLookup&lt;T&gt;">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ProvisionListenerBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.RequireAtInjectOnConstructorsOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.RequireExactBindingAnnotationsOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="option" type="com.google.inject.spi.RequireExplicitBindingsOption">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.ScopeBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="request" type="com.google.inject.spi.StaticInjectionRequest">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeConverterBinding">
+</parameter>
+</method>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binding" type="com.google.inject.spi.TypeListenerBinding">
+</parameter>
+</method>
+</interface>
+<class name="Elements"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Elements"
+ type="com.google.inject.spi.Elements"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stage" type="com.google.inject.Stage">
+</parameter>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="getModule"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elements" type="java.lang.Iterable&lt;? extends com.google.inject.spi.Element&gt;">
+</parameter>
+</method>
+</class>
+<interface name="ExposedBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="applyTo"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getPrivateElements"
+ return="com.google.inject.spi.PrivateElements"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="HasDependencies"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getDependencies"
+ return="java.util.Set&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="InjectionListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="afterInjection"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="injectee" type="I">
+</parameter>
+</method>
+</interface>
+<class name="InjectionPoint"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="forConstructor"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructor" type="java.lang.reflect.Constructor&lt;T&gt;">
+</parameter>
+</method>
+<method name="forConstructor"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="constructor" type="java.lang.reflect.Constructor&lt;T&gt;">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="forConstructorOf"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="forConstructorOf"
+ return="com.google.inject.spi.InjectionPoint"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="forInstanceMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="forInstanceMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="forStaticMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+<method name="forStaticMethodsAndFields"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;?&gt;">
+</parameter>
+</method>
+<method name="getDeclaringType"
+ return="com.google.inject.TypeLiteral&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDependencies"
+ return="java.util.List&lt;com.google.inject.spi.Dependency&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMember"
+ return="java.lang.reflect.Member"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isOptional"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isToolable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="InjectionRequest"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="InjectionRequest"
+ type="com.google.inject.spi.InjectionRequest"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+<parameter name="instance" type="T">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="R"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;R&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="ConfigurationException" type="com.google.inject.ConfigurationException">
+</exception>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="InstanceBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInstance"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="InterceptorBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getClassMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super java.lang.Class&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInterceptors"
+ return="java.util.List&lt;org.aopalliance.intercept.MethodInterceptor&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMethodMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="LinkedKeyBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getLinkedKey"
+ return="com.google.inject.Key&lt;? extends T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="MembersInjectorLookup"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="MembersInjectorLookup"
+ type="com.google.inject.spi.MembersInjectorLookup"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getDelegate"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="com.google.inject.TypeLiteral&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initializeDelegate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delegate" type="com.google.inject.MembersInjector&lt;T&gt;">
+</parameter>
+</method>
+</class>
+<class name="Message"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<constructor name="Message"
+ type="com.google.inject.spi.Message"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sources" type="java.util.List&lt;java.lang.Object&gt;">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getCause"
+ return="java.lang.Throwable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessage"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSources"
+ return="java.util.List&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="PrivateElements"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="getElements"
+ return="java.util.List&lt;com.google.inject.spi.Element&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExposedKeys"
+ return="java.util.Set&lt;com.google.inject.Key&lt;?&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExposedSource"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;?&gt;">
+</parameter>
+</method>
+<method name="getInjector"
+ return="com.google.inject.Injector"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getProvidedKey"
+ return="com.google.inject.Key&lt;?&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderInstanceBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProviderInstance"
+ return="com.google.inject.Provider&lt;? extends T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUserSuppliedProvider"
+ return="javax.inject.Provider&lt;? extends T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProviderKeyBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+<method name="getProviderKey"
+ return="com.google.inject.Key&lt;? extends javax.inject.Provider&lt;? extends T&gt;&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="ProviderLookup"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="ProviderLookup"
+ type="com.google.inject.spi.ProviderLookup"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getDelegate"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initializeDelegate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delegate" type="com.google.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+</class>
+<interface name="ProviderWithDependencies"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<implements name="com.google.inject.Provider">
+</implements>
+</interface>
+<interface name="ProviderWithExtensionVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Provider">
+</implements>
+<method name="acceptExtensionVisitor"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.BindingTargetVisitor&lt;B, V&gt;">
+</parameter>
+<parameter name="binding" type="com.google.inject.spi.ProviderInstanceBinding&lt;? extends B&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ProvidesMethodBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.HasDependencies">
+</implements>
+<method name="getEnclosingInstance"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="com.google.inject.Key&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMethod"
+ return="java.lang.reflect.Method"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="ProvidesMethodTargetVisitor"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.BindingTargetVisitor">
+</implements>
+<method name="visit"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providesMethodBinding" type="com.google.inject.spi.ProvidesMethodBinding&lt;? extends T&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="ProvisionListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onProvision"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provision" type="com.google.inject.spi.ProvisionListener.ProvisionInvocation&lt;T&gt;">
+</parameter>
+</method>
+</interface>
+<class name="ProvisionListener.ProvisionInvocation"
+ extends="java.lang.Object"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProvisionInvocation"
+ type="com.google.inject.spi.ProvisionListener.ProvisionInvocation"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getBinding"
+ return="com.google.inject.Binding&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDependencyChain"
+ return="java.util.List&lt;com.google.inject.spi.DependencyAndSource&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="provision"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProvisionListenerBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="R"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;R&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getBindingMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.Binding&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getListeners"
+ return="java.util.List&lt;com.google.inject.spi.ProvisionListener&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="RequireAtInjectOnConstructorsOption"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="RequireExactBindingAnnotationsOption"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="RequireExplicitBindingsOption"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ScopeBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getAnnotationType"
+ return="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getScope"
+ return="com.google.inject.Scope"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="StaticInjectionRequest"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getInjectionPoints"
+ return="java.util.Set&lt;com.google.inject.spi.InjectionPoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="ConfigurationException" type="com.google.inject.ConfigurationException">
+</exception>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="java.lang.Class&lt;?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Toolable"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="TypeConverter"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="convert"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+<parameter name="toType" type="com.google.inject.TypeLiteral&lt;?&gt;">
+</parameter>
+</method>
+</interface>
+<class name="TypeConverterBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<constructor name="TypeConverterBinding"
+ type="com.google.inject.spi.TypeConverterBinding"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="java.lang.Object">
+</parameter>
+<parameter name="typeMatcher" type="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;">
+</parameter>
+<parameter name="typeConverter" type="com.google.inject.spi.TypeConverter">
+</parameter>
+</constructor>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeConverter"
+ return="com.google.inject.spi.TypeConverter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="TypeEncounter"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="com.google.inject.spi.Message">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="arguments" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="addError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="java.lang.Throwable">
+</parameter>
+</method>
+<method name="bindInterceptor"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="methodMatcher" type="com.google.inject.matcher.Matcher&lt;? super java.lang.reflect.Method&gt;">
+</parameter>
+<parameter name="interceptors" type="org.aopalliance.intercept.MethodInterceptor...">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="getMembersInjector"
+ return="com.google.inject.MembersInjector&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="com.google.inject.Key&lt;T&gt;">
+</parameter>
+</method>
+<method name="getProvider"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="register"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="membersInjector" type="com.google.inject.MembersInjector&lt;? super I&gt;">
+</parameter>
+</method>
+<method name="register"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="com.google.inject.spi.InjectionListener&lt;? super I&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="TypeListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="hear"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="com.google.inject.TypeLiteral&lt;I&gt;">
+</parameter>
+<parameter name="encounter" type="com.google.inject.spi.TypeEncounter&lt;I&gt;">
+</parameter>
+</method>
+</interface>
+<class name="TypeListenerBinding"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.spi.Element">
+</implements>
+<method name="acceptVisitor"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visitor" type="com.google.inject.spi.ElementVisitor&lt;T&gt;">
+</parameter>
+</method>
+<method name="applyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="getListener"
+ return="com.google.inject.spi.TypeListener"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTypeMatcher"
+ return="com.google.inject.matcher.Matcher&lt;? super com.google.inject.TypeLiteral&lt;?&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="UntargettedBinding"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.Binding">
+</implements>
+</interface>
+</package>
+<package name="com.google.inject.spring"
+>
+<class name="SpringIntegration"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindAll"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+<parameter name="beanFactory" type="ListableBeanFactory">
+</parameter>
+</method>
+<method name="fromSpring"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.Class&lt;T&gt;">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.throwingproviders"
+>
+<interface name="CheckedProvider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+</interface>
+<class name="CheckedProvides"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<class name="ThrowingInject"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.annotation.Annotation">
+</implements>
+</class>
+<interface name="ThrowingProvider"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<implements name="com.google.inject.throwingproviders.CheckedProvider">
+</implements>
+<method name="get"
+ return="T"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+</interface>
+<class name="ThrowingProviderBinder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bind"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceType" type="java.lang.Class&lt;P&gt;">
+</parameter>
+<parameter name="typeLiteral" type="com.google.inject.TypeLiteral&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceType" type="java.lang.Class&lt;P&gt;">
+</parameter>
+<parameter name="clazz" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</method>
+<method name="bind"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, ?&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="interfaceType" type="java.lang.Class&lt;P&gt;">
+</parameter>
+<parameter name="clazz" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="create"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="binder" type="com.google.inject.Binder">
+</parameter>
+</method>
+<method name="forModule"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="module" type="com.google.inject.Module">
+</parameter>
+</method>
+</class>
+<class name="ThrowingProviderBinder.SecondaryBinder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SecondaryBinder"
+ type="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceType" type="java.lang.Class&lt;P&gt;">
+</parameter>
+<parameter name="valueType" type="java.lang.reflect.Type">
+</parameter>
+</constructor>
+<method name="annotatedWith"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotationType" type="java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;">
+</parameter>
+</method>
+<method name="annotatedWith"
+ return="com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder&lt;P, T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="annotation" type="java.lang.annotation.Annotation">
+</parameter>
+</method>
+<method name="providing"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cxtorLiteral" type="com.google.inject.TypeLiteral&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="providing"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cxtorClass" type="java.lang.Class&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="P">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetKey" type="com.google.inject.Key&lt;? extends P&gt;">
+</parameter>
+</method>
+<method name="to"
+ return="com.google.inject.binder.ScopedBindingBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetType" type="java.lang.Class&lt;? extends P&gt;">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.tools.jmx"
+>
+<interface name="ManagedBindingMBean"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getKey"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProvider"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="Manager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Manager"
+ type="com.google.inject.tools.jmx.Manager"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="main"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+<exception name="Exception" type="java.lang.Exception">
+</exception>
+</method>
+<method name="manage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="domain" type="java.lang.String">
+</parameter>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+<method name="manage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="server" type="javax.management.MBeanServer">
+</parameter>
+<parameter name="domain" type="java.lang.String">
+</parameter>
+<parameter name="injector" type="com.google.inject.Injector">
+</parameter>
+</method>
+</class>
+</package>
+<package name="com.google.inject.util"
+>
+<class name="Modules"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="combine"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="combine"
+ return="com.google.inject.Module"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<method name="override"
+ return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="override"
+ return="com.google.inject.util.Modules.OverriddenModuleBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modules" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+<field name="EMPTY_MODULE"
+ type="com.google.inject.Module"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="Modules.OverriddenModuleBuilder"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="with"
+ return="com.google.inject.Module"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overrides" type="com.google.inject.Module...">
+</parameter>
+</method>
+<method name="with"
+ return="com.google.inject.Module"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overrides" type="java.lang.Iterable&lt;? extends com.google.inject.Module&gt;">
+</parameter>
+</method>
+</interface>
+<class name="Providers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="guicify"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="javax.inject.Provider&lt;T&gt;">
+</parameter>
+</method>
+<method name="of"
+ return="com.google.inject.Provider&lt;T&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="instance" type="T">
+</parameter>
+</method>
+</class>
+<class name="Types"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="arrayOf"
+ return="java.lang.reflect.GenericArrayType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="componentType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="listOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elementType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="mapOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="valueType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="newParameterizedType"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rawType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="typeArguments" type="java.lang.reflect.Type...">
+</parameter>
+</method>
+<method name="newParameterizedTypeWithOwner"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ownerType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="rawType" type="java.lang.reflect.Type">
+</parameter>
+<parameter name="typeArguments" type="java.lang.reflect.Type...">
+</parameter>
+</method>
+<method name="providerOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="providedType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="setOf"
+ return="java.lang.reflect.ParameterizedType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="elementType" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="subtypeOf"
+ return="java.lang.reflect.WildcardType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bound" type="java.lang.reflect.Type">
+</parameter>
+</method>
+<method name="supertypeOf"
+ return="java.lang.reflect.WildcardType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bound" type="java.lang.reflect.Type">
+</parameter>
+</method>
+</class>
+</package>
+</api>
diff --git a/lib/build/header-definitions.xml b/lib/build/header-definitions.xml
new file mode 100644
index 0000000..84bf786
--- /dev/null
+++ b/lib/build/header-definitions.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<additionalHeaders>
+  <javadoc_style>
+    <firstLine>/**</firstLine>
+    <beforeEachLine> * </beforeEachLine>
+    <endLine> */&#10;</endLine>
+    <!--afterEachLine></afterEachLine-->
+    <!--skipLine></skipLine-->
+    <firstLineDetectionPattern>(\s|\t)*/\*.*$</firstLineDetectionPattern>
+    <lastLineDetectionPattern>.*\*/(\s|\t)*$</lastLineDetectionPattern>
+    <allowBlankLines>false</allowBlankLines>
+    <isMultiline>true</isMultiline>
+    <padLines>false</padLines>
+  </javadoc_style>
+</additionalHeaders>
diff --git a/lib/build/header.txt b/lib/build/header.txt
new file mode 100644
index 0000000..5d6a87e
--- /dev/null
+++ b/lib/build/header.txt
@@ -0,0 +1,13 @@
+Copyright (C) 2014 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.
diff --git a/lib/build/jarjar-1.1.jar b/lib/build/jarjar-1.1.jar
new file mode 100644
index 0000000..352c00a
--- /dev/null
+++ b/lib/build/jarjar-1.1.jar
Binary files differ
diff --git a/lib/build/javax.inject-tck.jar b/lib/build/javax.inject-tck.jar
new file mode 100644
index 0000000..49cc1f1
--- /dev/null
+++ b/lib/build/javax.inject-tck.jar
Binary files differ
diff --git a/lib/build/jdiff/Null.java b/lib/build/jdiff/Null.java
new file mode 100644
index 0000000..019b718
--- /dev/null
+++ b/lib/build/jdiff/Null.java
@@ -0,0 +1,9 @@
+/** 
+ * This class is used only as a "null" argument for Javadoc when comparing
+ * two API files. Javadoc has to have a package, .java or .class file as an 
+ * argument, even though JDiff doesn't use it.
+ */
+public class Null {
+    public Null() {
+    }
+}
diff --git a/lib/build/jdiff/background.gif b/lib/build/jdiff/background.gif
new file mode 100644
index 0000000..e6d2dda
--- /dev/null
+++ b/lib/build/jdiff/background.gif
Binary files differ
diff --git a/lib/build/jdiff/black.gif b/lib/build/jdiff/black.gif
new file mode 100644
index 0000000..185d95b
--- /dev/null
+++ b/lib/build/jdiff/black.gif
Binary files differ
diff --git a/lib/build/jdiff/jdiff.jar b/lib/build/jdiff/jdiff.jar
new file mode 100644
index 0000000..5fc7ed0
--- /dev/null
+++ b/lib/build/jdiff/jdiff.jar
Binary files differ
diff --git a/lib/build/jdiff/new.gif b/lib/build/jdiff/new.gif
new file mode 100644
index 0000000..c0ef7a4
--- /dev/null
+++ b/lib/build/jdiff/new.gif
Binary files differ
diff --git a/lib/build/jdiff/xerces.jar b/lib/build/jdiff/xerces.jar
new file mode 100644
index 0000000..e75d486
--- /dev/null
+++ b/lib/build/jdiff/xerces.jar
Binary files differ
diff --git a/lib/build/jsr305.jar b/lib/build/jsr305.jar
new file mode 100644
index 0000000..f973aea
--- /dev/null
+++ b/lib/build/jsr305.jar
Binary files differ
diff --git a/lib/build/junit.jar b/lib/build/junit.jar
new file mode 100644
index 0000000..674d71e
--- /dev/null
+++ b/lib/build/junit.jar
Binary files differ
diff --git a/lib/build/munge.jar b/lib/build/munge.jar
new file mode 100644
index 0000000..770cbd0
--- /dev/null
+++ b/lib/build/munge.jar
Binary files differ
diff --git a/lib/build/safesax.jar b/lib/build/safesax.jar
new file mode 100644
index 0000000..e54b10c
--- /dev/null
+++ b/lib/build/safesax.jar
Binary files differ
diff --git a/lib/build/spring-beans.jar b/lib/build/spring-beans.jar
new file mode 100644
index 0000000..93708dc
--- /dev/null
+++ b/lib/build/spring-beans.jar
Binary files differ
diff --git a/lib/build/spring-core.jar b/lib/build/spring-core.jar
new file mode 100644
index 0000000..f8b9b6a
--- /dev/null
+++ b/lib/build/spring-core.jar
Binary files differ
diff --git a/lib/guava-16.0.1.jar b/lib/guava-16.0.1.jar
new file mode 100644
index 0000000..2c8127d
--- /dev/null
+++ b/lib/guava-16.0.1.jar
Binary files differ
diff --git a/lib/javax.inject.jar b/lib/javax.inject.jar
new file mode 100644
index 0000000..a9dfb86
--- /dev/null
+++ b/lib/javax.inject.jar
Binary files differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..9cdc793
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,470 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Copyright (c) 2006 Google, Inc. All rights reserved.
+
+This program is licensed to you under the Apache License Version 2.0,
+and you may not use this file except in compliance with the Apache License Version 2.0.
+You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the Apache License Version 2.0 is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google</groupId>
+    <artifactId>google</artifactId>
+    <version>5</version>
+  </parent>
+
+  <packaging>pom</packaging>
+
+  <groupId>com.google.inject</groupId>
+  <artifactId>guice-parent</artifactId>
+  <version>4.0</version>
+
+  <name>Google Guice</name>
+
+  <description>
+    Guice is a lightweight dependency injection framework for Java 6 and above
+  </description>
+
+  <url>https://github.com/google/guice</url>
+  <inceptionYear>2006</inceptionYear>
+
+  <organization>
+    <name>Google, Inc.</name>
+    <url>http://www.google.com</url>
+  </organization>
+
+  <mailingLists>
+    <mailingList>
+      <name>Guice Users List</name>
+      <archive>http://groups.google.com/group/google-guice/topics</archive>
+      <subscribe>http://groups.google.com/group/google-guice/subscribe</subscribe>
+      <unsubscribe>http://groups.google.com/group/google-guice/subscribe</unsubscribe>
+      <post>http://groups.google.com/group/google-guice/post</post>
+    </mailingList>
+    <mailingList>
+      <name>Guice Developers List</name>
+      <archive>http://groups.google.com/group/google-guice-dev/topics</archive>
+      <subscribe>http://groups.google.com/group/google-guice-dev/subscribe</subscribe>
+      <unsubscribe>http://groups.google.com/group/google-guice-dev/subscribe</unsubscribe>
+      <post>http://groups.google.com/group/google-guice-dev/post</post>
+    </mailingList>
+  </mailingLists>
+
+  <scm>
+    <connection>scm:git:git://github.com/google/guice.git</connection>
+    <developerConnection>scm:git:ssh://git@github.com/google/guice.git</developerConnection>
+    <url>https://github.com/google/guice</url>
+  </scm>
+
+  <issueManagement>
+    <system>Google Code</system>
+    <url>https://github.com/google/guice/issues/</url>
+  </issueManagement>
+
+  <ciManagement>
+    <system>Travis</system>
+    <url>https://travis-ci.org/google/guice</url>
+  </ciManagement>
+
+  <licenses>
+    <license>
+      <name>The Apache Software License, Version 2.0</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+
+  <distributionManagement>
+    <!-- override the parent's directory to point to the canonical place, and use https. -->
+    <repository>
+      <id>google-releases</id>
+      <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+    </repository>
+    <snapshotRepository>
+      <id>google-snapshots</id>
+      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+    </snapshotRepository>
+  </distributionManagement>
+
+  <modules>
+    <module>bom</module>
+    <module>core</module>
+    <module>extensions</module>
+    <!-- jdk8-tests module activated only when running under JDK8, below -->
+  </modules>
+
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+
+  <properties>
+    <!--
+     | The spec version of the public Guice API
+    -->
+    <guice.api.version>1.4</guice.api.version>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <!--
+     | Use "-Dguice.with.jarjar=false" to build without jarjar
+    -->
+    <guice.with.jarjar>true</guice.with.jarjar>
+    <!--
+     | Use "-Dguice.with.no_aop=false" to skip the no-AOP variant
+    -->
+    <guice.with.no_aop>true</guice.with.no_aop>
+    <gpg.skip>true</gpg.skip>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>javax.inject</groupId>
+        <artifactId>javax.inject</artifactId>
+        <version>1</version>
+      </dependency>
+      <dependency>
+        <groupId>javax.inject</groupId>
+        <artifactId>javax.inject-tck</artifactId>
+        <version>1</version>
+      </dependency>
+      <dependency>
+        <groupId>aopalliance</groupId>
+        <artifactId>aopalliance</artifactId>
+        <version>1.0</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.guava</groupId>
+        <artifactId>guava</artifactId>
+        <version>16.0.1</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.guava</groupId>
+        <artifactId>guava-testlib</artifactId>
+        <version>16.0.1</version>
+      </dependency>
+      <dependency>
+        <groupId>org.ow2.asm</groupId>
+        <artifactId>asm</artifactId>
+        <version>5.0.3</version>
+      </dependency>
+      <dependency>
+        <groupId>cglib</groupId>
+        <artifactId>cglib</artifactId>
+        <version>3.1</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.11</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <!--
+     | Ant-style directories
+    -->
+    <sourceDirectory>${project.basedir}/src</sourceDirectory>
+    <resources>
+      <resource>
+        <filtering>false</filtering>
+        <directory>${project.basedir}/src</directory>
+        <excludes>
+          <exclude>**/*.java</exclude>
+        </excludes>
+      </resource>
+    </resources>
+    <testSourceDirectory>${project.basedir}/test</testSourceDirectory>
+    <testResources>
+      <testResource>
+        <filtering>false</filtering>
+        <directory>${project.basedir}/test</directory>
+        <excludes>
+          <exclude>**/*.java</exclude>
+        </excludes>
+      </testResource>
+    </testResources>
+    <pluginManagement>
+      <plugins>
+        <!--
+         | Use 'mvn license:format -N' at top of project to add missing headers
+        -->
+        <plugin>
+          <groupId>com.mycila</groupId>
+          <artifactId>license-maven-plugin</artifactId>
+          <version>2.6</version>
+          <configuration>
+            <encoding>UTF-8</encoding>
+            <header>${project.basedir}/lib/build/header.txt</header>
+            <headerDefinitions>
+              <headerDefinition>${project.basedir}/lib/build/header-definitions.xml</headerDefinition>
+            </headerDefinitions>
+            <skipExistingHeaders>true</skipExistingHeaders>
+            <aggregate>true</aggregate>
+            <includes>
+              <include>**/*.java</include>
+            </includes>
+            <excludes>
+              <!-- avoid touching munged/lib/test/example code -->
+              <exclude>**/build/**</exclude>
+              <exclude>**/target/**</exclude>
+              <exclude>**/lib/**</exclude>
+              <exclude>**/test/**</exclude>
+              <exclude>**/example*/**</exclude>
+            </excludes>
+            <mapping>
+              <java>JAVADOC_STYLE</java>
+            </mapping>
+          </configuration>
+        </plugin>
+        <!--
+         | Standard LICENSE and NOTICE files
+        -->
+        <plugin>
+          <artifactId>maven-remote-resources-plugin</artifactId>
+          <version>1.1</version>
+          <executions>
+            <execution>
+              <goals>
+                <goal>process</goal>
+              </goals>
+              <configuration>
+                <resourceBundles>
+                  <resourceBundle>org.apache:apache-jar-resource-bundle:1.4</resourceBundle>
+                </resourceBundles>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+        <!--
+         | Make sure we only use Java6 methods
+        -->
+        <plugin>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>2.3.2</version>
+          <configuration>
+            <source>1.6</source>
+            <target>1.6</target>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>animal-sniffer-maven-plugin</artifactId>
+          <version>1.10</version>
+          <configuration>
+            <signature>
+              <groupId>org.codehaus.mojo.signature</groupId>
+              <artifactId>java16</artifactId>
+              <version>1.0</version>
+            </signature>
+          </configuration>
+          <executions>
+            <execution>
+              <id>check-java-1.6-compat</id>
+              <phase>process-classes</phase>
+              <goals>
+                <goal>check</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>2.5</version>
+          <configuration>
+            <redirectTestOutputToFile>true</redirectTestOutputToFile>
+            <!--<argLine>-Dguice_include_stack_traces=OFF</argLine>-->
+          </configuration>
+          <executions>
+            <execution>
+              <id>stack-traces-off</id>
+              <phase>test</phase>
+              <goals><goal>test</goal></goals>
+              <configuration>
+                <argLine>-Dguice_include_stack_traces=OFF</argLine>
+              </configuration>
+            </execution>
+            <execution>
+              <id>stack-traces-complete</id>
+              <phase>test</phase>
+              <goals><goal>test</goal></goals>
+              <configuration>
+                <argLine>-Dguice_include_stack_traces=COMPLETE</argLine>
+              </configuration>
+            </execution>
+            <execution>
+              <id>default-test</id>
+              <phase>test</phase>
+              <goals><goal>test</goal></goals>
+              <configuration>
+                <argLine>-Dguice_include_stack_traces=ONLY_FOR_DECLARING_SOURCE</argLine>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+        <!--
+         | Shared OSGi manifest configuration
+        -->
+        <plugin>
+          <groupId>org.apache.felix</groupId>
+          <artifactId>maven-bundle-plugin</artifactId>
+          <version>2.1.0</version>
+          <configuration>
+            <instructions>
+              <module>com.google.inject</module>
+              <_include>-${project.basedir}/build.properties</_include>
+              <Bundle-Copyright>Copyright (C) 2006 Google Inc.</Bundle-Copyright>
+              <Bundle-DocURL>https://github.com/google/guice</Bundle-DocURL>
+              <Bundle-Name>${project.artifactId}</Bundle-Name>
+              <Bundle-SymbolicName>$(module)</Bundle-SymbolicName>
+              <Bundle-RequiredExecutionEnvironment>JavaSE-1.6</Bundle-RequiredExecutionEnvironment>
+              <Import-Package>!com.google.inject.*,*</Import-Package>
+              <_exportcontents>!*.internal.*,$(module).*;version=${guice.api.version}</_exportcontents>
+              <_versionpolicy>$(version;==;$(@))</_versionpolicy>
+              <_nouses>true</_nouses>
+              <_removeheaders>
+                Embed-Dependency,Embed-Transitive,
+                Built-By,Tool,Created-By,Build-Jdk,
+                Originally-Created-By,Archiver-Version,
+                Include-Resource,Private-Package,
+                Ignore-Package,Bnd-LastModified
+              </_removeheaders>
+            </instructions>
+          </configuration>
+          <executions>
+            <execution>
+              <phase>prepare-package</phase>
+              <goals>
+                <goal>manifest</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+        <!--
+         | Package OSGi manifest in final JAR, also create a JAR of the test classes
+        -->
+        <plugin>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>2.3.1</version>
+          <configuration>
+            <archive>
+              <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+              <!--  Exclude to mirror ant build -->
+          <addMavenDescriptor>false</addMavenDescriptor>
+            </archive>
+          </configuration>
+          <executions>
+            <execution>
+              <phase>package</phase>
+              <goals>
+                <goal>test-jar</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <artifactId>maven-javadoc-plugin</artifactId>
+          <version>2.7</version>
+          <executions>
+            <execution>
+              <phase>package</phase>
+              <goals>
+                <goal>jar</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <artifactId>maven-source-plugin</artifactId>
+          <version>2.1.2</version>
+          <executions>
+            <execution>
+              <phase>package</phase>
+              <goals>
+                <goal>jar</goal>
+                <goal>test-jar</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <artifactId>maven-release-plugin</artifactId>
+          <version>2.1</version>
+          <configuration>
+            <autoVersionSubmodules>true</autoVersionSubmodules>
+          </configuration>
+        </plugin>
+        <plugin>
+          <artifactId>maven-deploy-plugin</artifactId>
+          <version>2.5</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <!--
+       | Sign artifacts.
+      -->
+      <plugin>
+        <artifactId>maven-gpg-plugin</artifactId>
+        <version>1.4</version>
+        <executions>
+          <execution>
+            <id>sign-artifacts</id>
+            <phase>verify</phase>
+            <goals><goal>sign</goal></goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>jdk8</id>
+      <activation>
+        <jdk>[1.8,)</jdk>
+      </activation>
+      <!-- Activate jdk8-tests module only under JDK 8 -->
+      <modules>
+        <module>jdk8-tests</module>
+      </modules>
+      <!-- Disable doclint under JDK 8 -->
+      <reporting>
+      <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <additionalparam>-Xdoclint:none</additionalparam>
+            </configuration>
+          </plugin>
+        </plugins>
+      </reporting>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <additionalparam>-Xdoclint:none</additionalparam>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <!-- TODO(cgruber): Update the google parent pom or migrate to sonatype's -->
+</project>
diff --git a/util/compareBuilds.sh b/util/compareBuilds.sh
new file mode 100755
index 0000000..e81a7f4
--- /dev/null
+++ b/util/compareBuilds.sh
@@ -0,0 +1,105 @@
+#!/bin/bash
+## Compares the ant jars to the maven jars and makes sure they're the same
+## (or different where/how expected)
+
+## Note: The no_aop build doesn't compare cleanly for some reason.
+## Maybe a difference between the ant & maven munge preprocessor?
+
+RETVAL=0
+
+function cleanAndBuild {
+  mvn clean > /dev/null
+  ant clean.all > /dev/null
+  #ant no_aop > /dev/null
+  ant dist > /dev/null
+  mvn package -DskipTests=true -Dmaven.javadoc.skip=true > /dev/null
+  #ant -f build/no_aop/build.xml dist > /dev/null
+}
+
+function findAndCompareJars {
+  version=4.0
+  for ANT in `find ./build/dist/* -name "*-snapshot.jar" `
+  do
+    if [ $ANT = "./build/dist/guice-snapshot.jar" ]; then
+      ## Check the main build.
+      MVN=./core/target/guice-$version-SNAPSHOT.jar
+      extension=core
+      compareJars "$ANT" "$MVN" $extension
+      #compareJars "./build/no_aop/$ANT" "./core/target/guice-$version-SNAPSHOT-no_aop.jar" "no_aop: $extension" 
+    else
+      ## Check extensions.
+      extension=`echo $ANT | awk -F"-" '{print $2 }'` 
+      MVN=./extensions/$extension/target/guice-$extension-$version-SNAPSHOT.jar  
+      compareJars "$ANT" "$MVN" $extension
+    fi
+
+  done;
+}
+
+function compareJars {
+  ANT=$1
+  MVN=$2
+  extension=$3
+  curdir=`pwd`
+ 
+  echo Comparing $3
+  mkdir "tmp$$"
+  cp $ANT tmp$$/ant.jar
+  cp $MVN tmp$$/mvn.jar
+  cd "tmp$$" 
+  mkdir ant
+  mkdir mvn
+  cd ant
+  jar -xf ../ant.jar
+  cd ..
+  cd mvn
+  jar -xf ../mvn.jar
+  cd ..
+  
+  ## ant puts LICENSE & NOTICE files in a different place
+  echo LICENSE > excludes
+  echo NOTICE >> excludes
+  ## ant does not create DEPENDENCIES
+  echo DEPENDENCIES >> excludes
+  ## ant/mvn slightly different in MANIFEST.MF
+  echo MANIFEST.MF >> excludes
+  
+  ## ant leaves empty directories for some jarjar'd paths --
+  ## we grep -v instead of exclude because we want to make sure
+  ## if any files in those directories exist, that they're diff'd.
+  ## ant 1.8+ also creates package-info classes all the time, and
+  ## maven doesn't -- so we just ignore the package-info classes.
+  diff -u --recursive -Xexcludes ant mvn | \
+     grep -v "^Only in ant/com/google/inject/internal/asm: signature$" | \
+     grep -v "^Only in ant/com/google/inject/internal/cglib: beans$" | \
+     grep -v "^Only in ant/com/google/inject/internal/cglib: transform$" | \
+     grep -v "^Only in ant/com/google/inject/internal/cglib/transform: impl$" | \
+     grep -v "^Only in ant/com/google/inject/internal/cglib: util$" | \
+     grep -v "^Only in ant: net$" | \
+     grep -v "^Only in ant: org$" | \
+     grep -v "^Only in ant/com/google/inject/.*: package-info\.class$"
+  # failure is 0 because we're using grep -v to filter things out
+  if [ $? -eq 0 ]; then
+    export RETVAL=1
+  fi
+  cd "$curdir"
+  rm -rf "tmp$$"
+}
+
+## Only bother doing this on the jdk8/mvn build (before we publish snapshots).
+## Otherwise it's a waste of time building mvn+ant each time.
+if [ "$TRAVIS_JDK_VERSION" == "oraclejdk8" ] && \
+   [ "$LABEL" == "mvn" ]; then
+  echo "Cleaning and building ant & maven..."
+  cleanAndBuild
+  echo "Starting to compare jars..."
+  echo
+  findAndCompareJars
+  if [ $RETVAL -eq 0 ]; then
+    echo "Everything looks good!"
+    exit 0
+  else
+    echo "Some things don't match -- see above for details."
+    exit 1
+  fi
+fi
diff --git a/util/generate-latest-docs.sh b/util/generate-latest-docs.sh
new file mode 100755
index 0000000..683c5fd
--- /dev/null
+++ b/util/generate-latest-docs.sh
@@ -0,0 +1,30 @@
+# see http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/ for details
+
+if [ "$TRAVIS_REPO_SLUG" == "google/guice" ] && \
+   [ "$TRAVIS_JDK_VERSION" == "oraclejdk8" ] && \
+   [ "$LABEL" == "ant" ] && \
+   [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
+   [ "$TRAVIS_BRANCH" == "master" ]; then
+  echo -e "Publishing javadoc & JDiff...\n"
+  rm -rf build/docs
+  ant javadoc jdiff
+  cp -R build/docs/javadoc $HOME/javadoc-latest
+  cp -R build/docs/latest-api-diffs $HOME/api-diffs-latest
+  cp lib/build/jdiff/*.gif $HOME/api-diffs-latest/
+
+  cd $HOME
+  git config --global user.email "travis@travis-ci.org"
+  git config --global user.name "travis-ci"
+  git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/google/guice gh-pages > /dev/null
+  
+  cd gh-pages
+  git rm -rf api-docs/latest/api-diffs api-docs/latest/javadoc
+  mkdir -p api-docs/latest
+  cp -rf $HOME/api-diffs-latest api-docs/latest/api-diffs
+  cp -rf $HOME/javadoc-latest api-docs/latest/javadoc
+  git add -f .
+  git commit -m "Lastest javadoc & api-diffs on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages"
+  git push -fq origin gh-pages > /dev/null
+
+  echo -e "Published Javadoc & JDiff to gh-pages.\n"
+fi
diff --git a/util/publish-snapshot-on-commit.sh b/util/publish-snapshot-on-commit.sh
new file mode 100755
index 0000000..19b571b
--- /dev/null
+++ b/util/publish-snapshot-on-commit.sh
@@ -0,0 +1,17 @@
+# see https://coderwall.com/p/9b_lfq
+
+if [ "$TRAVIS_REPO_SLUG" == "google/guice" ] && \
+   [ "$TRAVIS_JDK_VERSION" == "oraclejdk8" ] && \
+   [ "$LABEL" == "mvn" ] && \
+   [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
+   [ "$TRAVIS_BRANCH" == "master" ]; then
+  echo -e "Publishing maven snapshot...\n"
+
+  cd $HOME
+  git clone --quiet --branch=travis https://github.com/google/guice travis > /dev/null
+  cd -
+  
+  mvn clean deploy --settings="$HOME/travis/settings.xml" -DskipTests=true -Dmaven.javadoc.skip=true
+
+  echo -e "Published maven snapshot"
+fi